目录
思考:dp[i]为什么要假设为以第i为结尾的最长递增子序列长度?
前沿:撰写博客的目的是为了再刷时回顾和进一步完善,其次才是以教为学,所以如果有些博客写的较简陋,是为了保持进度不得已而为之,还请大家多多见谅。
预:看到题目后的思路和实现的代码。
见:参考答案展示。
感思:对比答案后的思考,与之前做过的题目是否有关联。
行:
(1)对于没做出来的题目,阅读答案后重新做一遍;
(2)下次做题可以尝试改善的方向;
(3)有助于理解的相关的题目
优先级:做题进度>学习&总结>默写回顾>做题数量
题目回顾
动态规划相关章节
代码随想录刷LeetCode | day39 动态规划刷题回顾
动态规划五步法:
- 确定dp数组以及下标的含义
确定递推公式
dp数组如何初始化
确定遍历顺序
举例推导dp数组
1.300.最长递增子序列
题目链接:300.最长递增子序列
思考:dp[i]为什么要假设为以第i为结尾的最长递增子序列长度?
- dp[i]以第i为结尾的最长递增子序列长度
- 若不以i为结尾,假设以遍历到i时的最长长度。
- 当以i节点>先前节点时,无法获得以该先前节点为结尾的最长长度,则不能直接写出递推公式即dp[i] = dp[j]+1不成立。
- 只有以i为结尾,才能便于后面比较获得递推公式。
- 若不以i为结尾,假设以遍历到i时的最长长度。
class Solution {
public int lengthOfLIS(int[] nums) {
int len = nums.length;
int[] dp = new int[len];
int result = 1;
for(int i = 0;i < len;i++){
dp[i] = 1;
}
for(int i = 1;i < len;i++){
for(int j = 0;j < i;j++){
if(nums[i] > nums[j]){
dp[i] = Math.max(dp[j]+1,dp[i]);
}
}
result = Math.max(dp[i],result);
}
return result;
}
}
2. 674. 最长连续递增序列
题目链接:674. 最长连续递增序列
思考:与300.最长递增子序列 的区别在哪?
- 最长递增子序列需要与之前的节点全部比较,因为其不需要连续。
- 最长连续递增序列则只需与前一个节点比较,若大于则等于前一节点+1。
class Solution {
public int findLengthOfLCIS(int[] nums) {
/*
连续子序列→dp[i]以i为结束的最长连续子序列长度
nums[i] < nums[i + 1],dp[i] = dp[i-1]+1;
nums[i] >= nums[i + 1],dp[i] = 1
*/
int len = nums.length;
int[] dp = new int[len];
dp[0] = 1;
int result = 1;
for(int i = 1;i < len;i++){
if(nums[i] > nums[i-1]){
dp[i] = dp[i-1]+1;
result = Math.max(dp[i],result);
}else{
dp[i] = 1;
}
}
return result;
}
}
3. 718. 最长重复子数组
题目链接:718. 最长重复子数组
思考:为什么会做错?
- dp[i][j]假设为遍历到 i 和 j 时最长的重复子数组。
- 所以即使不相等也会赋值给其左上的最大值。
- 但若其下节点相等时,则会导致重复考虑。
- 正确的dp[i][j]假设:以[i][j]为结尾时最长的重复子数组。
- 每次相等时都是在[i-1][j-1]基础上+1,避免重复判断相加的情况。
class Solution {
public int findLength(int[] nums1, int[] nums2) {
int len1 = nums1.length;
int len2 = nums2.length;
int[][] dp = new int[len1+1][len2+1];
int result = 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;
result = Math.max(result,dp[i][j]);
}
}
}
return result;
}
}
4. 1143.最长公共子序列
题目链接:1143.最长公共子序列
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
int len1 = text1.length();
int len2 = text2.length();
int[][] dp = new int[len1+1][len2+1];
//int result = 0;
for(int i = 1;i <= len1;i++){
for(int j = 1;j <= len2;j++){
if(text1.charAt(i-1) == text2.charAt(j-1)){
dp[i][j] = dp[i-1][j-1]+1;
}else{
dp[i][j] = Math.max(dp[i][j-1],dp[i-1][j]);
}
//result = Math.max(dp[i][j],result);
}
}
return dp[len1][len2];
}
}
5.1035.不相交的线
题目链接:1035.不相交的线
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
int len1 = text1.length();
int len2 = text2.length();
int[][] dp = new int[len1+1][len2+1];
//int result = 0;
for(int i = 1;i <= len1;i++){
for(int j = 1;j <= len2;j++){
if(text1.charAt(i-1) == text2.charAt(j-1)){
dp[i][j] = dp[i-1][j-1]+1;
}else{
dp[i][j] = Math.max(dp[i][j-1],dp[i-1][j]);
}
//result = Math.max(dp[i][j],result);
}
}
return dp[len1][len2];
}
}
6. 53. 最大子序和 动态规划
题目链接:53. 最大子序和 动态规划
class Solution {
public int maxSubArray(int[] nums) {
int len = nums.length;
//int[] dp = new int[len];
//dp[0] = nums[0];
int dp = nums[0];
int result = dp;
for(int i = 1;i < len;i++){
if(dp <= 0){
dp = nums[i];
}else{
dp = dp + nums[i];
}
result = Math.max(result,dp);
}
return result;
}
}