目录
讀題
1143.最长公共子序列
自己看到题目的第一想法
看完代码随想录之后的想法
1035.不相交的线
自己看到题目的第一想法
53. 最大子序和
看完代码随想录之后的想法
1143.最长公共子序列 - 實作
思路
Code
1035.不相交的线 - 實作
思路
Code
53. 最大子序和 - 實作
思路
Code
總結
自己实现过程中遇到哪些困难
今日收获,记录一下自己的学习时长
相關資料
1143.最长公共子序列
1035.不相交的线
53. 最大子序和
讀題
1143.最长公共子序列
自己看到题目的第一想法
看起來跟最長重複子数組很類似,但是要怎麼去推遞推的狀態沒有想法
看完代码随想录之后的想法
看完之後,大概釐清了整體想法,可以想成說,因為我們要考慮的是不連續的子序列,所以會分成兩種狀態,一個是不相同,不相同的話需要看之前的序列有沒有重複,之前包括兩個方面,縱向與橫向關係,要取最大的,因為這個緣故,在相同的時候,因為之前的數都考慮過縱向與橫向的關係,可以直接從左上角跟重複子序列一樣,求出該值。 至於初始化的部分,在定義下標時,i、j都設定為i - 1 或者說 1 ~ i ,讓後續的遞推公式以及初始化都可以比較簡便。
1035.不相交的线
自己看到题目的第一想法
看到這題,看到卡哥的提示,觀察過後其實就跟最長的公共子序列一樣,如果有一個子序列是共有的,那最長的公共子序列一定是可以連接最多不相交的線,整體的概念是一致的。
53. 最大子序和
看完代码随想录之后的想法
其實整體概念跟連續遞增子序有點像,改為將数組變動 dp[i - 1] + nums[i] 以及 nums[i]的差異,看完程式碼後理解上不會太過於困難。
1143.最长公共子序列 - 實作
思路
-
定義DP數組以及下標的含意
dp[i][j] 代表 0~ i - 1 的text1 以及 0 ~ j - 1 的text2 最长公共子序列長度為dp[i][j]
-
遞推公式
分成兩種狀態相同與不相同
不相同的話需要看之前的序列有沒有重複,之前包括兩個方面,縱向與橫向關係,要取最大的
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
相同的時候,因為之前的數都考慮過縱向與橫向的關係,可以直接從左上角跟重複子序列一樣
dp[i][j] = dp[i - 1][j - 1] + 1;
-
根據遞推公式、題意以及定義,確定DP數組如何初始化
最少為0,所以初始化為0
-
確定遍歷順序
因為需要左上角的數據來進行遍歷,所以是由前往後。
Code
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
vector<vector<int>> dp (text1.size() + 1, vector<int>(text2.size() + 1, 0));
for(int i = 1; i < text1.size() + 1; i++) {
for(int j = 1; j < text2.size() + 1; j++) {
if(text1[i - 1] == text2[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1;
else dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
return dp[text1.size()][text2.size()];
}
};
1035.不相交的线 - 實作
思路
-
定義DP數組以及下標的含意
dp[i][j] 代表 0~ i - 1 的nums1 以及 0 ~ j - 1 的nums2 最长不相交的线為dp[i][j]
-
遞推公式
分成兩種狀態相同與不相同
不相同的話需要看之前的序列有沒有重複,之前包括兩個方面,縱向與橫向關係,要取最大的
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
相同的時候,因為之前的數都考慮過縱向與橫向的關係,可以直接從左上角跟重複子序列一樣
dp[i][j] = dp[i - 1][j - 1] + 1;
-
根據遞推公式、題意以及定義,確定DP數組如何初始化
最少為0,所以初始化為0
-
確定遍歷順序
因為需要左上角的數據來進行遍歷,所以是由前往後。
Code
class Solution {
public:
int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {
vector<vector<int>> dp (nums1.size() + 1, vector<int>(nums2.size() + 1, 0));
for(int i = 1; i < nums1.size() + 1; i++) {
for(int j = 1; j < nums2.size() + 1; j++) {
if(nums1[i - 1] == nums2[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1;
else dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
return dp[nums1.size()][nums2.size()];
}
};
53. 最大子序和 - 實作
思路
-
定義DP數組以及下標的含意
dp[i] 代表 i 之前包含i 的number[i] 結尾的最大子序和是多少
-
遞推公式
當前的数加上前面的數比較大還是當前的數比較大,取大的。
dp[i] = max(dp[i - 1] + nums[i], nums[i])
if dp [i] > result 更新result
-
根據遞推公式、題意以及定義,確定DP數組如何初始化
將數組初始化為最小值,以及result = nums[0]
-
確定遍歷順序
0 到 i 因為需要前面的數據來進行遍歷,所以是由前往後。
Code
class Solution {
public:
int maxSubArray(vector<int>& nums) {
vector<int> dp (nums.size() + 1, INT_MIN);
int result = nums[0];
dp[0] = nums[0];
for(int i = 1; i < nums.size(); i++ ) {
dp[i] = max(dp[i - 1] + nums[i], nums[i]);
if(dp[i] > result) result = dp[i];
}
return result;
}
};
總結
自己实现过程中遇到哪些困难
一開始對於最長公共子序列不太了解,但看完講解後,其實就是在重複子序列的基礎上考慮橫向與縱向的關係,以及最大子序和整體很像最長連續子序列,只是思考上需要進行轉換﹐整體而言,今天題目主要是思路上需要做一些改變,不然很容易繞進去。
今日收获,记录一下自己的学习时长
今天大概學習了2hr,整體是很充實的,尤其理解最長公共子序列,在想法上接續到的二題不相交的線就會非常清晰。
相關資料
● 今日学习的文章链接和视频链接
1143.最长公共子序列
视频讲解:动态规划子序列问题经典题目 | LeetCode:1143.最长公共子序列_哔哩哔哩_bilibili
https://programmercarl.com/1143.最长公共子序列.html
1035.不相交的线
视频讲解:动态规划之子序列问题,换汤不换药 | LeetCode:1035.不相交的线_哔哩哔哩_bilibili
https://programmercarl.com/1035.不相交的线.html
53. 最大子序和
视频讲解:看起来复杂,其实是简单动态规划 | LeetCode:53.最大子序和_哔哩哔哩_bilibili文章来源:https://www.toymoban.com/news/detail-734782.html
https://programmercarl.com/0053.最大子序和(动态规划).html文章来源地址https://www.toymoban.com/news/detail-734782.html
到了这里,关于代碼隨想錄算法訓練營|第五十五天|1143.最长公共子序列、1035.不相交的线、53. 最大子序和。刷题心得(c++)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!