673. 最長遞增子序列的個數
阿新 • • 發佈:2018-12-24
給定一個未排序的整數陣列,找到最長遞增子序列的個數。
示例 1:
輸入: [1,3,5,4,7]
輸出: 2
解釋: 有兩個最長遞增子序列,分別是 [1, 3, 4, 7] 和[1, 3, 5, 7]。
示例 2:
輸入: [2,2,2,2,2]
輸出: 5
解釋: 最長遞增子序列的長度是1,並且存在5個子序列的長度為1,因此輸出5。
注意: 給定的陣列長度不超過 2000 並且結果一定是32位有符號整數。
解題思路:
定義 dp(n,1) cnt (n,1)
這裡我用dp[i]表示以nums[i]為結尾的遞推序列的長度,用cnt[i]表示以nums[i]為結尾的遞推序列的個數,初始化都賦值為1,只要有數字,那麼至少都是1。然後我們遍歷陣列,對於每個遍歷到的數字nums[i],我們再遍歷其之前的所有數字nums[j],當nums[i]小於等於nums[j]時,不做任何處理,因為不是遞增序列。反之,則判斷dp[i]和dp[j]的關係,如果dp[i]等於dp[j] + 1,說明nums[i]這個數字可以加在以nums[j]結尾的遞增序列後面,並且以nums[j]結尾的遞增序列個數可以直接加到以nums[i]結尾的遞增序列個數上。如果dp[i]小於dp[j] + 1,說明我們找到了一條長度更長的遞增序列,那麼我們此時獎dp[i]更新為dp[j]+1,並且原本的遞增序列都不能用了,直接用cnt[j]來代替。維護一個全域性最長的子序列長度mx,每次都進行更新,到最後遍歷一遍每個節點,如果長度等於mx,res+=cnt[i];
code:
class Solution { public: int findNumberOfLIS(vector<int>& nums) { int n = nums.size(), max_len = 1, res = 0; vector<int> dp(n, 1), cnt(n, 1); //dp記錄以i結尾的最長子序列長度 ,cnt記錄以i結尾的最長子序列的個數 for(int i = 1; i < n; ++i){ for(int j = 0; j < i; ++j){ if(nums[j] < nums[i] && dp[j] + 1 > dp[i]){ dp[i] = dp[j] + 1; cnt[i] = cnt[j]; } else if(nums[j] < nums[i] && dp[j] + 1 == dp[i]){ cnt[i] += cnt[j]; } } max_len = max(max_len, dp[i]); } for(int i = 0; i < n; ++i) if(dp[i] == max_len) res += cnt[i]; return res; } };