JavaScript 实现最长非降低子序列

题目

首先先引一道动态规划的经典问题 最长非降低子序列 它的定义是: 设有由n个不相同的整数组成的数列b[n],如有下标i1<i2<···<iL 且 b[i1]<b[i2]<···<b[iL] 则称存在一个长度为L的不降低序列。git

例如:github

13,7,9,16,38,24,37,18,44,19,21,22,63,15数组

那么就有13<16<38<44<63长度为5的不降低子序列。 可是通过观察实际上还有7<9<16<18<19<21<22<63长度为8的不降低子序列,那么是否还有更长的不降低子序列呢?请找出最长的不降低子序列code

要求实现一个方法,输入参数是一个数组,返回最长的非降低子序列ip

实现思路

假如要求得某一段的最优,就要想更小段的最优怎么求,再看看由最小段的最优可否扩大推广到最大段的最优;get

假设这么一个表input

序列下标 0 1 2 3 4 5 6 7 8 9 10 11 12 13
序列数值 13 7 9 16 38 24 37 18 44 19 21 22 63 15
序列长度 1 1 1 1 1 1 1 1 1 1 1 1 1 1
连接位置 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1

第三行表示该序列元素的所能链接的最长不降低子序列的长度,由于自己长度为1,因此初始值都为1. 第四行表示连接于哪一个序列元素造成最长不降低子序列it

再看倒数第三项22,在它的后面有2项,所以必需要在这2项当中找出比22大,长度又是最长的数值做为连接,因为只有22<63,因此修改22的长度为2,即自身长度加上所连接数值的长度,并修改连接位置为12,也就是63的下标。io

再看倒数第四项21,在它的后面有3项,所以必需要在这3项当中找出比21大,长度又是最长的数值做为连接(注意:是长度),很容易看出,数值22知足该条件,所以,修改21的长度为3,并修改连接位置为11,即22的序列下标。console

依次类推,最后结果以下表:

序列下标 0 1 2 3 4 5 6 7 8 9 10 11 12 13
序列数值 13 7 9 16 38 24 37 18 44 19 21 22 63 15
序列长度 7 8 7 6 3 4 3 5 2 4 3 2 1 1
连接位置 3 2 3 7 8 6 8 9 12 10 11 12 -1 -1

最终状态的转移方程式为: 且 \(f(i)=maxf(j)+1(b_j<b_i且i<j)\) .时间复杂度为O(n^2)

JavaScript 实现

function getLongAscArr(inputArr) {
        var numArr = [1];
        var idxArr = [-1];
        var len = inputArr.length;
        for (var l = len - 1; l--;) {
            var num = 1;
            var idx = -1;
            var nLen = numArr.length;
            for (var i = 0; i < nLen; i++) {
                var nIdx = l en - nLen + i;
                if (inputArr[l] <= i nputArr[nIdx]) {
                    if (numArr[i] >= num) {
                        num = numArr[i] + 1;
                        idx = nIdx;
                    }
                }
            }
            numArr.unshift(num);
            idxArr.unshift(idx);
        }
        var max = numArr[0];
        var idx = 0;
        for (var i = 1; i < numArr.length; i++) {
            if (numArr[i] > max) {
                max = numArr[i];
                idx = i;
            }
        }
        var ascArr = [];
        while (idx > -1) {
            ascArr.push(inputArr[idx]);
            idx = idxArr[idx];
        }
        return ascArr;
    }
    var arr = [13, 7, 9, 16, 38, 24, 37, 18, 44, 19, 21, 22, 63, 15];
    console.log(getLongAscArr(arr));

参考资料

https://xxsxjh.github.io/2017/02/02/Dynamic-1/

相关文章
相关标签/搜索