给定一个0和1的数组,找出包含多个连续k 0和多个连续k 1的最长子序列的长度。
注意:在你的子序列之前可以有0,之后可以有1,但不能同时发生,否则你的子序列不是最长的。
找到一个非常复杂的算法。
这就是我目前的处境。

int subsequence(int v[], int dim){
int i, k_0=0, k_1=0, count_0=0, count_1=0, prev=-1;
for (i = 0; i < dim; i++) {

    if (v[i] == 0 && prev == 1) {
        count_0 = 0;
        count_1 = 0;
        k_0 = k_1 = (k_0 < k_1) ? k_0 : k_1;
    }

    if (v[i] == 0) {
        count_0 += 1;
    }

    if (v[i] == 1) {
        count_1 += 1;
    }

    k_0 = (count_0 > k_0) ? count_0: k_0;
    k_1 = (count_1 > k_1) ? count_1: k_1;
    prev = v[i];
}
return (k_0 < k_1) ? k_0 : k_1;

}
Complexity O(n)

有没有更好的方法来解决这个问题?

最佳答案

更好的方法是通过更清晰的算法实现正确地声明和定义函数。
第一个参数应具有限定符const,第二个参数应具有类型size_t。函数返回类型也应为size_t
在函数中,首先应该找到第一个等于0的元素,然后才处理数组的其余部分。
我将按以下方式编写函数

#include <stdio.h>

size_t longest_subsequence( const int a[], size_t n )
{
    const int value1 = 0;
    const int value2 = 1;

    size_t longest = 0;

    size_t i = 0;
    while ( i < n && a[i] != value1 ) i++;

    while ( i < n )
    {

        size_t n1 = i;

        while ( i < n && a[i] == value1 ) i++;

        size_t n2 = i;

        while ( i < n && a[i] == value2 ) i++;

        n1 = n2 - n1;
        n2 = i - n2;

        n1 = n2 < n1 ? n2 : n1;

        if ( longest < 2 * n1 ) longest = 2 * n1;
    }

    return longest;
}

int main(void)
{
    int a[] = { 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1 };
    const size_t N = sizeof( a ) / sizeof( *a );

    printf( "%zu\n", longest_subsequence( a, N ) );

    return 0;
}

程序输出是
6

实际上,数组中最长的子序列是
{ 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1 };
                                ^^^^^^^^^^^^^^^^

或者计算出的值看起来像
if ( longest < n1 ) longest = n1;

主要的是,如何计算并不重要。

关于c - 求出包含多个连续k 0s以及随后多个连续k 1s的最长子序列的长度,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57994039/

10-10 05:30