1143. 最长公共子序列
这题有点像递增子序列和公共子数组的组合, 要求公共子序列不一定非要是连续的。
- 确定dp数组下标及其含义
dp[i][j]表示text1[i - 1]与text2[j - 1]结尾的最高公共子序列。
长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符串text2的最长公共子序列为dp[i][j]
最后返回的结果是**dp[text1.length()][text2.length()],**因为这里不相等并不是推倒重新再来,因此遍历到最后一定是最大的。
- 确定递推公式
text1[i - 1]和text2[j - 1]相等和不相等。
相等:dp[i][j] = dp[i - 1][j - 1] + 1
不相等:dp[i][j] = max(dp[i-1][j],dp[i][j-1])(相当于对两个字符串错开进行对齐)
- 初始化
全为0即可;
- 遍历顺序
从前往后。
- 举例推导dp数组
最终代码:
class Solution {public int longestCommonSubsequence(String text1, String 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++) {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]);}}}return dp[text1.length()][text2.length()];}
}
1035. 不相交的线(和1143代码一摸一样)
本题的关键在于转化,实际上和1143找最长子序列是一样的代码。(我怎么看不出来!!!)
还真是一样的代码,修改完直接AC:
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][j - 1], dp[i - 1][j]);}}}return dp[nums1.length][nums2.length];}
}
怎么样才能画出不相交的线:让相同的数按照相同的相对顺序出现 ,实际上也就是求最长公共子序列。
之前贪心就做过了,这里贴一下贪心解法:
class Solution {public int maxSubArray(int[] nums) {//贪心:先累加,当前和为负数时放弃,统计最大。int sum = 0;int maxSum = Integer.MIN_VALUE;for(int i = 0; i < nums.length; i++){if(sum < 0){sum = 0;}sum += nums[i];maxSum = maxSum = Integer.max(sum , maxSum);}return maxSum;}}
动态规划
- 确定dp数组下标及其含义
dp[i]:包括下标i(以nums[i]为结尾)的最大连续子序列和为dp[i]
- 确定递推公式
dp[i]只有两个方向可以推出来:
dp[i - 1] + nums[i],即:nums[i]加入当前连续子序列和
nums[i],即:从头开始计算当前连续子序列和
一定是取最大的,所以dp[i] = max(dp[i - 1] + nums[i], nums[i]);
- 初始化
dp[0] = nums[0]
- 遍历顺序
从前到后,用res记录最大值
- 举例推导dp数组
最终代码:
class Solution {public int maxSubArray(int[] nums) {int dp[] = new int[nums.length];dp[0] = nums[0];int result = nums[0];//dp[i]表示包括下标i(以nums[i]为结尾)的最大连续子序列和为dp[i]for (int i = 1; i < nums.length; i++) {dp[i] = Math.max(nums[i] + dp[i - 1], nums[i]);result = Math.max(result, dp[i]);}return result;}
}