题目
思路
- 明确每次做动态规划的题目一定要用递归思路思考问题,如何把大问题分成小问题
- 思路一:递归,定义recur(String text1, int i, String text2, int j)表示字符串text1前i和字符串text2前j的最大长度,每次比较我们只比较text1.charAt(i)是否等于text2.charAt(j)即可,是则加1,并且继续寻找下一个recur(text1,i+1,text2,j+1),如果不相等我们选择recur(text1,i+1,text2,j)和recur(text1,i,text2,j+1)的最大值
- 思路二:备忘录
- 思路三:动态规划,基于递归
- 思路四:优化dp数组的动态规划,基于思路三
代码
//1.暴力递归 public int longestCommonSubsequence(String text1, String text2){ return recur(text1, 0, text2, 0); } public int recur(String text1, int i, String text2, int j) { if (i >= text1.length() || j >= text2.length()) return 0; if (text1.charAt(i) == text2.charAt(j)) { return recur(text1, i + 1, text2, j + 1) + 1; } else { return Math.max(recur(text1, i, text2, j + 1), recur(text1, i + 1, text2, j)); } } //2.备忘录 int[][] dp; public int longestCommonSubsequence(String text1, String text2){ dp = new int[text1.length()][text2.length()]; for (int i = 0; i < text1.length(); i++) { for (int j = 0; j < text2.length(); j++) { dp[i][j] = -1; } } return recur(text1, 0, text2, 0); } public int recur(String text1, int i, String text2, int j) { if (i >= text1.length() || j >= text2.length()) return 0; if (dp[i][j] != -1) return dp[i][j]; int res = 0; if (text1.charAt(i) == text2.charAt(j)) { res = recur(text1, i + 1, text2, j + 1) + 1; } else { res = Math.max(recur(text1, i, text2, j + 1), recur(text1, i + 1, text2, j)); } dp[i][j] = res; return res; } //3.动态规划 public int longestCommonSubsequence(String text1, String text2) { //dp[i][j]表示text1[0~i-1]与text2[0~j-1]的最大子序列长度,只是把备忘录的拿过来 int[][] dp = new int[text1.length() + 1][text2.length() + 1]; for (int i = 0; i <= text1.length(); i++) { dp[i][0] = 0; } for (int j = 0; j <= text2.length(); j++) { dp[0][j] = 0; } for (int i = 0; i < text1.length(); i++) { for (int j = 0; j < text2.length(); j++) { if (text1.charAt(i) == text2.charAt(j)) { dp[i + 1][j + 1] = dp[i][j] + 1; } else { dp[i + 1][j + 1] = Math.max(dp[i][j + 1], dp[i + 1][j]) ; } } } return dp[text1.length()][text2.length()]; } //4.动态规划,优化dp数组,由于每次只用到前一列和前一个,因此可以优化为一维 public int longestCommonSubsequence(String text1, String text2) { int[] dp = new int[text2.length() + 1]; for (int j = 0; j <= text2.length(); j++) { dp[j] = 0; } for (int i = 0; i < text1.length(); i++) { for (int j = 0, prev = dp[0]; j < text2.length(); j++) { int t = dp[j + 1]; if (text1.charAt(i) == text2.charAt(j)) { dp[j + 1] = prev + 1; } else { dp[j + 1] = Math.max(dp[j + 1], dp[j]) ; } prev = t; } } return dp[text2.length()]; }
最大公共子序列