「程式碼隨想錄演算法訓練營」第三十七天 | 動態規劃 part10

云雀AC了一整天發表於2024-08-14

300. 最長遞增子序列

題目連結:https://leetcode.cn/problems/longest-increasing-subsequence/
文章講解:https://programmercarl.com/0300.最長上升子序列.html
題目難度:中等
影片講解:https://www.bilibili.com/video/BV1ng411J7xP
題目狀態:有思路,但是自己能寫出來還是太勉強,有些細節想不到

思路:

維護一個動規陣列dp[i],表示在遍歷到陣列中的第i個元素的時候,此時能找到的最長遞增子序列的長度。

其更新的程式碼如下:if(num[i] > num[j]) dp[i] = max(dp[i], dp[j] + 1);

所以需要有兩次遍歷,i是整個陣列的遍歷,j是在當前元素前面的元素,這樣就能確保dp[i]是當前最大的遞增子序列的個數。

程式碼:

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        if(nums.size() <= 1) return nums.size();
        vector<int> dp(nums.size(), 1);
        int ans = 0;
        for(int i = 1; i < nums.size(); ++i) {
            for(int j = 0; j < i; ++j) {
                if(nums[i] > nums[j]) dp[i] = max(dp[i], dp[j] + 1);
            }
            ans = ans < dp[i] ? dp[i] : ans;
        }
        return ans;
    }
};

674. 最長連續遞增序列

題目連結:https://leetcode.cn/problems/longest-continuous-increasing-subsequence/
文章講解:https://programmercarl.com/0674.最長連續遞增序列.html
題目難度:簡單
影片講解:https://www.bilibili.com/video/BV1bD4y1778v
題目狀態:這題比較簡單,久違的獨立透過

思路:

相較於上題,這題很簡單,dp陣列的更新只要依靠前一個元素就可以,若當前元素大於前一個元素,就將前一個元素的dp陣列加1。

程式碼:

class Solution {
public:
    int findLengthOfLCIS(vector<int>& nums) {
        if(nums.size() <= 1) return nums.size();
        vector<int> dp(nums.size(), 1);
        int ans = 0;
        for(int i = 1; i < nums.size(); ++i) {
            if(nums[i] > nums[i - 1]) dp[i] = dp[i - 1] + 1;
            ans = ans < dp[i] ? dp[i] : ans;
        }
        return ans;
    }
};

貪心思路和程式碼:

維護一個變數count用來存放當前的連續遞增序列的長度,如果遇到nums[i] > nums[i - 1]的情況,count就++,否則count就為1,記錄count的最大值就可以了。

class Solution {
public:
    int findLengthOfLCIS(vector<int>& nums) {
        if(nums.size() <= 1) return nums.size();
        int ans = 0;
        int count = 1;
        for(int i = 1; i < nums.size(); ++i) {
            if(nums[i] > nums[i - 1]) count++;
            else count = 1;
            ans = ans < count ? count : ans;
        }
        return ans;
    }
};

718. 最長重複子陣列

題目連結:https://leetcode.cn/problems/maximum-length-of-repeated-subarray/
文章講解:https://programmercarl.com/0718.最長重複子陣列.html
題目難度:中等
影片講解:https://www.bilibili.com/video/BV178411H7hV
題目狀態:看題解

思路

維護一個二維動規陣列d[i][j],表示在陣列1中元素為i-1和陣列2中元素為j-1時的最長重複子陣列的大小。

若要更新這個動規陣列,我們要進行巢狀迴圈,第一個迴圈是陣列1,第二個迴圈是陣列2,其更新的條件是nums1[i - 1] = nums2[j - 1],至於為什麼是i-1和j-1,因為這樣我們可以從1開始比較,避免處理i或j為0時的特殊情況。

程式碼

class Solution {
public:
    int findLength(vector<int>& nums1, vector<int>& nums2) {
        int len1 = nums1.size();
        int len2 = nums2.size();
        int ans = 0;
        vector<vector<int>> dp(len1 + 1, vector<int>(len2 + 1, 0));
        for(int i = 1; i <= len1; ++i) {
            for(int j = 1; j <= len2; ++j) {
                if(nums1[i - 1] == nums2[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1;
                ans = ans < dp[i][j] ? dp[i][j] : ans;
            }
        }
        return ans;
    }
};

相關文章