2D矩阵中最长的子序列。

时间:2016-01-27 08:44:15

标签: algorithm dynamic-programming

我正在解决编程挑战,以找到2D NxN矩阵中最长增长子序列的长度。行和列必须在序列的每个元素中增加(不需要是连续的)。我用动态编程方法解决了它,但它是O(N ^ 4)并且效率低下。但是,O(N ^ 3)中有许多解决方案。一个这样的解决方案是:

   scanf("%d", &N);
    for(i = 1; i <= N; i++) {
        for(j = 1; j <= N; j++) {
            scanf("%d", &L[i][j]);
        }
    }
    Answer = 0; 

    memset(maxLength,0,sizeof(maxLength));
    for (i=1;i<=N;i++) 
    {
        maxLength[1][i] = 1;
        maxLength[i][1] = 1;
    }

    //
    for (i=2;i<=N;i++)
    {

        memset(minValue,0,sizeof(minValue));
        curLen = 1;
        minValue[1] = L[i-1][1]; 

        for (j=2;j<=N;j++)  
        {
            for (p=1;p<i;p++)
            {
                tmpLen = maxLength[p][j-1];
                if (minValue[tmpLen] == 0)
                {
                    minValue[tmpLen] = L[p][j-1]; 
                    curLen = tmpLen;
                }
                else if (minValue[tmpLen]>L[p][j-1])
                {
                    minValue[tmpLen] = L[p][j-1];
                }
            }


            max = 1;
            for (p=curLen;p>0;p--)
            {
                if (L[i][j]>=minValue[p])
                {
                    max = p+1;
                    break;
                }
            }

            maxLength[i][j] = max;
            Answer = Answer>max?Answer:max;
        }
    }

    // Print the answer to standard output(screen).
    printf("%d\n", Answer);

有人可以解释它的工作原理或任何其他O(N ^ 3)方法吗?我根本无法遵循它:(。

1 个答案:

答案 0 :(得分:3)

O(n 3 时间内解决这个问题并不困难。但是,我没有阅读源代码,因此我不知道它是否具有以下功能,但这里有一个关于如何完成它的想法。

诀窍在于更新程序。我想你最初做的是以下内容。

enter image description here

假设您正在考虑橙色矩形中的元素。上一步必须来自蓝色矩形(您已经解决了)。这会产生正确答案,但很容易看出它会产生Θ(n 4 结果,因为你可以制作橙色和蓝色矩形 Θ(n 2 ,您需要考虑它们之间的所有对。 (这很容易形式化。)

相反,首先只解决第一行和第一列。实际上,在每次迭代中,取下一个未解决的行和列,并从先前解决的部分中解决它们。

enter image description here

这是诀窍(我将留给你)。如果在单元格中存储足够的信息(或者在辅助数据结构中存储,则无关紧要),那么对于您正在考虑的橙色列中的每个元素,您只需要查看其左侧的列(同上)对于橙色行 - 您只需要查看其上方行中的元素。)

所以有 O(n)外部迭代(在每一个中你考虑一行和一列)。每个这样的行/列具有 O(n)元素,并且每个左/上行/列具有 O(n)元素2。乘法给出了目标的复杂性。