首先先引一道动态规划的经典问题 最长非降低子序列 它的定义是: 设有由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));