如何在O(n log n)时间内从阵列中的每个位置开始找到最长的增加序列,

时间:2012-10-18 06:42:25

标签: algorithm optimization data-structures sequence dynamic-programming

我们如何在O(n log n)时间内从阵列的每个位置开始找到最长的增加子序列,我已经看到了在阵列的每个位置找到最长增长序列的技术,但我无法找到反过来说。

e.g。 对于序列“3 2 4 4 3 2 3” 输出必须是“2 2 1 1 1 2 1”

2 个答案:

答案 0 :(得分:1)

我做了一个快速而又脏的JavaScript实现(注意:它是O(n ^ 2)):

function lis(a) {
    var tmpArr = Array(),
        result = Array(),
        i = a.length;

    while (i--) {
        var theValue = a[i],
            longestFound = tmpArr[theValue] || 1;

        for (var j=theValue+1; j<tmpArr.length; j++) {
            if (tmpArr[j] >= longestFound) {
                longestFound = tmpArr[j]+1;
            }
        }
        result[i] = tmpArr[theValue] = longestFound;
    }
    return result;
}

jsFiddle: http://jsfiddle.net/Bwj9s/1/

我们从右到左遍历数组,将先前的计算保存在单独的临时数组中,以便后续查找。

tmpArray包含以前找到的以任何给定值开头的子序列,因此tmpArray[n]将表示从值n开始找到的最长子序列(位于当前位置的右侧)

循环如下:对于每个索引,我们在tmpArray中查找值(以及所有更高的值),看看我们是否已经找到了可以预先附加值的子序列。如果我们找到一个,我们只需在该长度上加1,更新值的tmpArray,然后移到下一个索引。如果我们找不到工作(更高)的子序列,我们将值的tmpArray设置为1并继续。


为了使它成为O(n log n),我们观察到tmpArray将始终是一个递减的数组 - 它可以而且应该使用二进制搜索而不是部分循环。

答案 1 :(得分:0)

编辑:我没有完全阅读帖子,抱歉。我认为你需要所有序列中增长最长的子序列。重新编辑代码以使其工作。

我认为实际上可以在线性时间内完成。请考虑以下代码:

int a[10] = {4, 2, 6, 10, 5, 3, 7, 5, 4, 10};
int maxLength[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // array of zeros
int n = 10; // size of the array;

int b = 0;


while (b != n) {
  int e = b;     
  while (++e < n && a[b] < a[e]) {} //while the sequence is increasing, ++e
  while (b != e) { maxLength[b++] = e-b-1; }
}