1. 程式人生 > >673. 最長遞增子序列的個數

673. 最長遞增子序列的個數

給定一個未排序的整數陣列,找到最長遞增子序列的個數。

示例 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;
    }
};