1035. 不相交的线
和最长公共子序列题目思路完全一致,相当于换了个问法,开始没反应过来。
class Solution {
public int maxUncrossedLines(int[] nums1, int[] nums2) {
int[][] dp = new int[nums1.length+1][nums2.length+1];
int result = 0;
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]);
}
result = Math.max(result,dp[i][j]);
}
}
return result;
}
}
优化空间复杂度:
class Solution {
public int maxUncrossedLines(int[] nums1, int[] nums2) {
int[] dp = new int[nums2.length+1];
int result = 0;
for(int i = 1;i <= nums1.length;i++){
int pre = dp[0];
for(int j = 1;j <= nums2.length;j++){
int cur = dp[j];
if(nums1[i-1] == nums2[j-1]){
dp[j] = pre + 1;
}else{
dp[j] = Math.max(dp[j],dp[j-1]);
}
result = Math.max(result,dp[j]);
pre = cur;
}
}
return result;
}
}
53. 最大子序和
这题还得是双指针,动态规划效率太低了
class Solution {
public boolean isSubsequence(String s, String t) {
int[][] dp = new int[s.length()+1][t.length()+1];
int res = 0;
for(int i = 1;i <= s.length();i++){
for(int j = 1;j <= t.length();j++){
if(s.charAt(i-1) == t.charAt(j-1)){
dp[i][j] = dp[i-1][j-1] + 1;
}else{
dp[i][j] = dp[i][j-1];
}
res = Math.max(res,dp[i][j]);
}
}
if(res == s.length()){
return true;
}
return false;
}
}
115. 不同的子序列
画图理解该题目
dp[i] [j] 表示以nums[i]为结尾的字符串有多少个以nums[j]为结尾的字符串子序列。
判断序列删除一个元素是否有子序列。
为什么还要考虑 不用s[i - 1]来匹配,都相同了指定要匹配啊?
例如: s:bagg 和 t:bag ,s[3] 和 t[2]是相同的,但是字符串s也可以不用s[3]来匹配,即用s[0]s[1]s[2]组成的bag。
当然也可以用s[3]来匹配,即:s[0]s[1]s[3]组成的bag。 所以当s[i - 1] 与 t[j - 1]相等时,dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]; 当s[i - 1] 与 t[j - 1]不相等时,dp[i][j]只有一部分组成,不用s[i - 1]来匹配(就是模拟在s中删除这个元素),即:dp[i - 1][j]
class Solution {
public int numDistinct(String s, String t) {
int[][] dp = new int[t.length()+1][s.length()+1];
for(int i = 0;i <= s.length();i++){
dp[0][i] = 1;
}
for(int i = 1;i <= t.length();i++){
for(int j = 1;j <= s.length();j++){
if(s.charAt(j-1) == t.charAt(i-1)){
dp[i][j] = dp[i-1][j-1] + dp[i][j-1];
}else{
dp[i][j] = dp[i][j-1];
}
}
}
return dp[t.length()][s.length()];
}
}