问题背景
给定两个字符串 t e x t 1 text_1 text1 和 t e x t 2 text_2 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0 0 0。
一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。
- 例如,“ace” 是 “abcde” 的子序列,但 “aec” 不是 “abcde” 的子序列。
两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。
数据约束
- 1 ≤ t e x t 1 . l e n g t h , t e x t 2 . l e n g t h ≤ 1000 1 \le text_1.length, text_2.length \le 1000 1≤text1.length,text2.length≤1000
- t e x t 1 text_1 text1 和 t e x t 2 text_2 text2 仅由小写英文字符组成。
解题过程
比较套路化的动态规划题,注意遇到两个字符相等时必选,不相等时不用考虑都不选的情形就可以了。
滚动数组的写法没能完全理解,暂时不强求。
具体实现
递归
class Solution {private char[] chT1, chT2;private int[][] memo;public int longestCommonSubsequence(String text1, String text2) {chT1 = text1.toCharArray();chT2 = text2.toCharArray();int m = chT1.length;int n = chT2.length;memo = new int[m][n];for (int[] row : memo) {Arrays.fill(row, -1);}return dfs(m - 1, n - 1);}private int dfs(int i, int j) {if (i < 0 || j < 0) {return 0;}if (memo[i][j] != -1) {return memo[i][j];}if (chT1[i] == chT2[j]) {return memo[i][j] = dfs(i - 1, j - 1) + 1;}return memo[i][j] = Math.max(dfs(i - 1, j), dfs(i, j - 1));}
}
递推
class Solution {public int longestCommonSubsequence(String text1, String text2) {char[] chT1 = text1.toCharArray();char[] chT2 = text2.toCharArray();int m = chT1.length;int n = chT2.length;int[][] dp = new int[m + 1][n + 1];for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {dp[i + 1][j + 1] = chT1[i] == chT2[j] ? dp[i][j] + 1 : Math.max(dp[i][j + 1], dp[i + 1][j]);}}return dp[m][n];}
}