动态规划 --- 序列问题
53.最大子数组和
解题思路: 动态规划
- 定义
dp数组含义: 以i结尾的最大子数组和 - 当加上当前位置的连续子数组和 > 当前元素时, 代表前缀和有益, 需要保留
- 当加上当前位置的连续子数组和 < 当前元素时, 代表前缀和无益, 需要舍弃
- 不是以终点为最优解, 需要在动规过程中不断记录最大值
代码:
class Solution {
public int maxSubArray(int[] nums) {
int n = nums.length;
int[] dp = new int[n];
dp[0] = nums[0];
int ans = nums[0];
for(int i=1; i < n; i++){
dp[i] = Math.max(dp[i-1] + nums[i], nums[i]);
ans = Math.max(ans, dp[i]);
}
return ans;
}
}
1143.最长公共子序列
解题思路: 动态规划
- 比较两个字符串, 数组, 子序列的公共部分: 二维
dp dp数组含义:ch1以i-1结尾,ch2以j-1结尾的最长公共子序列长度为dp[i][j]- 当两个比较位置的字符相等时:
dp[i][j] = dp[i-1][j-1] + 1 - 当不相等时, 需要延续其之前相等的状态:
dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1])
代码:
class Solution {
// 两个数组, 字符串, 序列求公共问题: 二维dp
public int longestCommonSubsequence(String text1, String text2) {
char[] ch1 = text1.toCharArray();
char[] ch2 = text2.toCharArray();
// dp数组含义: ch1以i+1结尾, ch2以j+1结尾的最长公共子序列长度为dp[i][j]
int[][] dp = new int[ch1.length + 1][ch2.length + 1];
int ans = 0;
for(int i=1; i <= ch1.length; i++){
for(int j=1; j<=ch2.length; j++){
if(ch1[i-1] == ch2[j-1]){
dp[i][j] = dp[i-1][j-1] + 1;
}else dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
ans = Math.max(ans, dp[i][j]);
}
}
return ans;
}
}
1035.不相交的线
解题思路: 动态规划 --- 与1035题完全相同
代码:
class Solution {
public int maxUncrossedLines(int[] nums1, int[] nums2) {
int m = nums1.length, n = nums2.length;
int[][] dp = new int[m + 1][n + 1];
for(int i=1; i <= m; i++){
for(int j=1; j <= n; j++){
if(nums1[i-1] == nums2[j-1]){
dp[i][j] = dp[i][j-1] + 1;
}else dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
}
}
return dp[m][n];
}
}