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/

相關文章
相關標籤/搜索