动态规划之LIS
这几天看了不少讲动态规划的书和文章,一般第一个例子就是斐波那契。这个例子真直观,可以将递归发,然后讲自顶向下,自底向上,都没问题。
动态规划还好嘛,not so hard。
但是,从第二个问题开始就不那么直观了。
最喜欢被人用的第二个例子就是这个LIS
Longest increasing sequence.
从一个序列里找出最长的升序子序列的长度:
比如:10,22,9,33,21,50,41,60,80 这个数字序列的最长生升序子序列是10 22 33 50 60 80 , 长度是6。最长升序子序列就是LIS,题目就是要找一个序列的LIS的长度
第一次看的时候以为要找最长子串。后来看了例子才发现不是,子序列里的数不一定在原来的序列里是紧挨着的,只要满足后面比前面大就行。
思路就一层窗户纸。 假设dp[i] = 结尾为i的序列的LIS长度。 那么dp[i+1]是多少呢?那要看第i+1个数字能不能和前面的数字组成新的IS(increasing sequence)。如果能,就在这些IS里面挑个最长(Longest)的。
写个状态转移方程:
dp: f(i)= max(f(j)+1 | 0<j<i && a[i]>=a[j] ) a[i]表示序列里第i个数字的值。
python实现
1 def lis(a): 2 l = len(a) 3 dp = [1 for i in range(l)] 4 for i in range(1,l): 5 for j in range(i): 6 if a[i] > a[j]: 7 dp[i] = max(dp[j]+1,dp[i]) 8 return dp[l-1] 9 10 test = [10,22,9,33,21,50,41,60,80] 11 print (lis(test))