找到最长的非减少子序列

时间:2012-12-26 17:37:16

标签: c sequence

给定一个字符串只包含0和1表示 10101
如何找到最长非减少子序列的长度?
例如,

  

表示字符串,
  10101

最长的非递减子序列是

  • 111
  • 001
    所以你应该输出3
  

表示字符串
  101001

最长的非递减子序列是

  • 0001

所以你应该输出4
怎么找到这个?

  
    

如果我们获得限制,怎么办?限制之间的序列
    例如
    101001个
    限制[3,6]
    最长的非减少子序列是

         
        
  • 001
        所以你应该输出3
  •     
  

可以在o(strlen)

中实现

3 个答案:

答案 0 :(得分:1)

  

这可以在O(strlen)

中实现

是。观察到非递减子序列将具有以下三种形式之一:

0........0 // Only zeros
1........1 // Only ones
0...01...1 // Some zeros followed by some ones

通过计算所有零并计算所有零,可以在O(1)中轻松检查前两个表单。

最后一个有点困难:你需要通过字符串保持你到目前为止看到的零的计数器,以及你发现的0...01...1形式的最长字符串的长度至今。在您在字符串中看到1的每个步骤中,第三个表单的最长子序列的长度是零的数量加上您看到的一个或最长的0...01...1序列中的较大者远一加。

以下是C语言中上述方法的实现:

char *str = "10101001";
int longest0=0, longest1=0;
for (char *p = str ; *p ; p++) {
    if (*p == '0') {
        longest0++;
    } else { // *p must be 1
        longest1 = max(longest0, longest1)+1;
    }
}
printf("%d\n", max(longest0, longest1));

max定义如下:

#define max( a, b ) ( ((a) > (b)) ? (a) : (b) )

这是link to a demo on ideone

答案 1 :(得分:1)

使用dynamic programming。从左到右贯穿字符串,并跟踪两个变量:

  • zero:以0结尾的最长子序列的长度
  • one:以1
  • 结尾的最长子序列的长度

如果我们看到0,我们可以将其附加到以0结尾的任何前缀,因此我们增加zero。如果我们看到1,我们可以将它附加到以0结尾的前缀或1中,因此我们将one设置为最长的那个。在C99:

int max(int a, int b) {
  return a > b ? a : b;
}

int longest(char *string) {
  int zero = 0;
  int one = 0;
  for (; *string; ++string) {
    switch (*string) {
      case '0':
        ++zero;
        break;
      case '1':
        one = max(zero, one) + 1;
        break;
    }
  }
  return max(zero, one);
}

答案 2 :(得分:0)

do {
    count++;
    if (array[i] < prev) {
        if (count > max)
            max = count;
        count = 0;
    }
    prev = array[i];
} while (++i < length);

单通。甚至可以处理任何数字,而不仅仅是1和0。

对于限制 - 将i设置为起始编号,请使用结束而不是数组长度。