線性dp:LeetCode674. 最長連續遞增序列

Tomorrowland_D發表於2024-08-24

LeetCode674. 最長連續遞增序列

  • 閱讀本文之前,需要先了解“動態規劃方法論”,這在我的文章以前有講過

連結:動態規劃方法論

  • 本文之前也講過一篇文章:最長遞增子序列,這道題,閱讀本文的同時可以與“最長遞增子序列進行對比”,這樣更能對比二者的區別!

LeetCode300.最長遞增子序列 - Tomorrowland_D - 部落格園 (cnblogs.com)

  • leetcode連結如下

力扣題目連結:

題目敘述

給定一個未經排序的整數陣列,找到最長且 連續遞增的子序列,並返回該序列的長度。

連續遞增的子序列 可以由兩個下標 l 和 r(l < r)確定,如果對於每個 l <= i < r,都有 nums[i] < nums[i + 1] ,那麼子序列 [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]] 就是連續遞增子序列。

示例 1:

  • 輸入:nums = [1,3,5,4,7]
  • 輸出:3
  • 解釋:最長連續遞增序列是 [1,3,5], 長度為3。儘管 [1,3,5,7] 也是升序的子序列, 但它不是連續的,因為 5 和 7 在原陣列裡被 4 隔開。

示例 2:

  • 輸入:nums = [2,2,2,2,2]
  • 輸出:1
  • 解釋:最長連續遞增序列是 [2], 長度為1。

提示:

  • 0 <= nums.length <= 10^4
  • -10^9 <= nums[i] <= 10^9

動態規劃思路講解:

  • 這道題與[最長遞增子序列](LeetCode300.最長遞增子序列 - Tomorrowland_D - 部落格園 (cnblogs.com))的區別就是,最長遞增子序列是可以不連續的,而最長連續遞增序列必須要是連續的。
  • 我們這道題仍然可以採用dp[i]的思想,而這裡的dp[i]與最長遞增子序列的dp[i]就差不多了,但不是完全一致

狀態變數及其含義

  • 我們可以設定狀態變數dp[i],表示以nums[i]為結尾的最長連續子序列的長度

遞推公式

  • 這裡我們不需要j指標,只需要將nums[i]與nums[i-1]作比較,判斷它們兩個是否能繼續構成連續遞增子序列,如果nums[i]<nums[i-1],證明nums[i]不能與nums[i-1]構成連續遞增子序列,所以說dp[i]=0

  • nums[i]>nums[i-1]時,意味nums[i]與前面能繼續構成連續遞增子序列,所以dp[i]=dp[i-1]+1

  • 故而遞推公式為:

    • dp[i]=0 (nums[i]<=nums[i-1]);
    • dp[i]=dp[i-1]+1 (nums[i]>nums[i-1])

遍歷順序

  • 這題dp[i]需要由dp[i-1]來推理出來,所以說遍歷順序顯然是從前向後遍歷。

如何初始化dp陣列?

  • 顯然,一開始dp陣列中的所有元素都初始化為1,因為每個元素至少都有一個最長連續遞增子序列。

舉例驗證dp陣列

  • 舉例:nums = [1,3,5,4,7]
    • dp[0]=1
    • dp[1]=2
    • dp[2]=3
    • dp[3]=0
    • dp[4]=2
  • 透過示例1的分析,我們也可以得知我們的dp陣列是正確的

程式碼實現:

class Solution {
public:
    int findLengthOfLCIS(vector<int>& nums) {
        //全都初始化為1
        vector<int> dp(nums.size(),1);
		//結果至少是1
        int ans=1;
        for(int i=1;i<nums.size();i++){
            if(nums[i]>nums[i-1]) dp[i]=dp[i-1]+1;
            ans=max(ans,dp[i]);
        }
        return ans;
    }
};

相關文章