標簽:
動態規划
描述:
Given a sequence of integers, find the longest increasing subsequence (LIS).
You code should return the length of the LIS.
Clarification
What's the definition of longest increasing subsequence?
-
The longest increasing subsequence problem is to find a subsequence of a given sequence in which the subsequence's elements are in sorted order, lowest to highest, and in which the subsequence is as long as possible. This subsequence is not necessarily contiguous, or unique.
解題思路:
經過將近四個小時的痛苦思考,最終還是無奈求助於答案。看來不看答案AC動態規划的問題還是需要一個過程的。真心羡慕餅王那樣的大神(北大數學系的牛逼人士,數學功底真的杠杠的),言歸正傳,這一道題是求最大增序列,可以不連續,但是必須是遞增。還是使用動態規划來解決這一問題:
1.划分子問題:
這一步驟基本算是考慮到了,例如一個長度為n的數列,可以划分為1->n的LIS,2->n的LIS,3->n的LIS。。。。n-1->n的LIS,但是這種解法存在問題,在於你在計算一個子問題的時候會出現多種增長序列,導致解不唯一。所以,划分子問題的時候應當將子序列的尾坐標依次從2到n,即1->2, 1->3, 1->4....1->n-1,1->n。之后再在每一個子問題中求出遞增序列
2.初始狀態的定義:
對於總的問題,可以定義一個max來作為存結果的變量
對於各個子問題,可以定義一個dp[]來對於先前每個子問題的結果進行記錄(備忘錄),並且在每個子問題開始前初始化為1,每種子問題最短也會有1.
3.子問題與遞進問題的關系(遞推公式):
在每個子問題中最大的值可以設置為子序列的最后一個元素即nums[i],只要存在先前元素小於最后一個元素即nums[j]<nums[i],說明在j到i呈增長趨勢,如果當前的最長長度若小於在j點的最長長度+1(在增長序列上再加上1),則該子問題的最長長度變為dp[j]+1.若大於的話說i與j之間存在下降趨勢。
公式為:
k[i] = k[i] (k[i]<K[j]+1)
K[i] = K[j]+1 (k[i]>K[j]+1)
4 參考代碼:
1 public int longestIncreasingSubsequence(int[] nums) { 2 // write your code here 3 if(nums.length==0){ 4 return 0; 5 } 6 int[] dp = new int[nums.length]; 7 int max = 0; 8 9 for(int i = 0; i<nums.length; i++){ 10 dp[i] =1; 11 for(int j = 0; j<i; j++){ 12 if(nums[j]<nums[i]){ 13 dp[i]=dp[i]<dp[j]+1?dp[j]+1:dp[i]; 14 } 15 16 } 17 if(dp[i]>max){ 18 max = dp[i]; 19 } 20 21 } 22 return max; 23 }
