首先先引一道動態規劃的經典問題 最長非降低子序列 它的定義是: 設有由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)
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));