1143.最长公共子序列
完成
思路:
定义二维dp数组,dp[i][j]
代表以i-1
结尾的text1
和以j-1
结尾的text2
的最长公共子序列长度,动态规划求子序列的相关问题中,dp数组这样定义是为了规避复杂的初始化,这是一个技巧。
代码
dp[i][j]
代表以i
结尾的text1
和以j
结尾的text2
的最长公共子序列长度
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
// dp[i][j]代表以i结尾的text1和以j结尾的text2 的最长公共子序列长度
int[][] dp = new int[text1.length()][text2.length()];
// 初始化开始--------------------------------------------------
// 需要初始化最上行和最左列
// 前面的元素为0,后一个元素需要比较得到;前面的元素为1,后一个元素一定是1
dp[0][0] = text1.charAt(0) == text2.charAt(0)?1:0;
int flag = dp[0][0];
for (int i = 1; i < text1.length(); i++) { // 初始化最左列
if(flag == 1){ // 前面的元素为1
dp[i][0] = 1;
}else{ // 前面的元素为0
if(text2.charAt(0) == text1.charAt(i)){
dp[i][0] = 1;
flag = 1;
}
}
}
flag = dp[0][0];
for (int j = 1; j < text2.length(); j++) { // 初始化最上行
if(flag == 1){
dp[0][j] = 1;
}else{
if(text1.charAt(0) == text2.charAt(j)){
dp[0][j] = 1;
flag = 1;
}
}
}
// 初始化结束----------------------------------------------------
for (int i = 1; i < text1.length(); i++) {
for (int j = 1; j < text2.length(); j++) {
if(text1.charAt(i)==text2.charAt(j)) dp[i][j] = Math.max(dp[i][j], dp[i-1][j-1]+1);
else dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
}
}
return dp[text1.length()-1][text2.length()-1];
}
}
dp[i][j]
代表以i-1
结尾的text1
和以j-1
结尾的text2
的最长公共子序列长度
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
// dp[i][j]代表以i-1结尾的text1和以j-1结尾的text2 的最长公共子序列长度
int[][] dp = new int[text1.length()+1][text2.length()+1];
for (int i = 1; i <= text1.length(); i++) {
for (int j = 1; j <= text2.length(); j++) {
// 注意这里不是 i 和 j
if(text1.charAt(i-1)==text2.charAt(j-1)) dp[i][j] = Math.max(dp[i][j], dp[i-1][j-1]+1);
else dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
}
}
return dp[text1.length()][text2.length()];
}
}
1035.不相交的线
完成
思路:
乍一看被吓到了,感觉判断线是否相交就不容易了,仔细分析发现其实就是找相同子序列。
和上一题的思路完全一样
代码
class Solution {
public int maxUncrossedLines(int[] nums1, int[] nums2) {
int[][] dp = new int[nums1.length+1][nums2.length+1];
for (int i = 1; i <= nums1.length; i++) {
for (int j = 1; j <= nums2.length; j++) {
if(nums1[i-1] == nums2[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]);
}
}
return dp[nums1.length][nums2.length];
}
}
53. 最大子序和
完成
思路:
贪心法做过。
动态规划 dp[i]代表以i结尾的数组中 最大子数组和,递推公式 dp[i] = Math.max(dp[i - 1] + nums[i], nums[i])
,需要注意的是,结果不一定从dp[len]
处取,而是要在遍历过程中记录下最值。
代码
class Solution {
public int maxSubArray(int[] nums) {
// dp[i]代表以i结尾的数组中 最大子数组和
int[] dp = new int[nums.length];
dp[0] = nums[0];
int res = nums[0];
for (int i = 1; i < nums.length; i++) {
// 前面的累加结果保留 前面的结果丢弃,从nums[i]开始算
dp[i] = Math.max(dp[i-1]+nums[i], nums[i]);
res = Math.max(res, dp[i]);
}
return res;
}
}