1. 程式人生 > >動態規劃——最長升序子序列及其個數

動態規劃——最長升序子序列及其個數

new 需要 遞增 -m amp 多次 兩個 fin incr

673. 最長遞增子序列的個數
1
public int findNumberOfLIS(int[] nums) { 2 int n=nums.length; 3 if(n==0||n==1)return n; 4 int []dp=new int[n]; 5 int []cnt=new int[n]; 6 int i,j,max=0,res=0; 7 Arrays.fill(dp, 1); 8 Arrays.fill(cnt, 1); 9 for
(i=1;i<n;i++){ 10 for(j=0;j<i;j++){ 11 if(nums[i]>nums[j]&&dp[i]<=dp[j]){ 12 dp[i]=dp[j]+1; 13 cnt[i]=cnt[j]; 14 }else if(nums[i]>nums[j]&&dp[i]==dp[j]+1) 15 cnt[i]+=cnt[j];
16 } 17 max=Math.max(dp[i],max); 18 } 19 for(i=0;i<n;i++) 20 if(dp[i]==max) 21 res+=cnt[i]; 22 return res; 23 }

首先要清楚dp[i]存放的是什麽。之前想當然的認為dp[i]=0..i最長的自增子序列長度,若是如此,那麽dp[]便為非降序數組,然而事實並非如此。通過查看dp[]的增長方式便知,其需要滿足兩個條件nums[i]>nums[j]&&dp[i]<=dp[j]

,關鍵的是dp[i]<=dp[j],若沒有這個條件,在多次叠代後會有許多重復計算。而最長子序列個數的增長是建立在所有前序狀態上的,也就是組合的思想。當nums[i]>nums[j]&&dp[i]==dp[j]+1時,也就是再一次滿足了最長子序列的條件,但是並不改變當前dp[i]的值(避免多重計算)此時,當前最長子序列增長。

動態規劃——最長升序子序列及其個數