题目链接:https://leetcode.com/problems/longest-palindromic-subsequence/description/
题目大意:找出最长回文子序列(不连续),第5题是最长回文子串。
法一(借鉴):dp,与5题,最长回文子串进行比较,这个dp更难一点。代码如下(耗时51ms):
1 //dp公式:dp[i,j]=2表示下标i到j的字符串中,最长回文子序列长度是2 2 //当s[i]=s[j]时,dp[i,j]=dp[i+1,j-1]+2 3 //当s[i]!=s[j]时,dp[i,j]=max(dp[i+1,j],dp[i,j-1]) 4 public int longestPalindromeSubseq(String s) { 5 int length = s.length(); 6 int dp[][] = new int[length][length]; 7 for(int i = length - 1; i >= 0; i--) {//从后向前dp计算,不知道为什么。。。 8 dp[i][i] = 1; 9 for(int j = i + 1; j < length; j++) {//逐一查看每个字符串中的字符序列是否有回文 10 if(s.charAt(i) == s.charAt(j)) { 11 dp[i][j] = dp[i + 1][j - 1] + 2; 12 } 13 else { 14 dp[i][j] = Math.max(dp[i][j - 1], dp[i + 1][j]); 15 } 16 } 17 } 18 return dp[0][length - 1]; 19 }
dp数组(例子:bbab):
0("b") | 1("b") | 2("a") | 3("b") | |
0("b") | 1(b) | 2(bb) | 2(bba) | 3(bbab) |
1("b") | 1(b) | 1(ba) | 3(bab) | |
2("a") | 1(a) | 1(ab) | ||
3("b") | 1(b) |
可以从上表看出最后结果在dp[0][3]中。
dp数组填充顺序:从下向上,每次计算都使用左边、下边,左下的数据。
法二(借鉴):记忆性搜索,其实感觉还是dp的思想,但是会比纯dp快。代码如下(耗时39ms):
1 public int longestPalindromeSubseq(String s) { 2 return dfs(s, 0, s.length() - 1, new int[s.length()][s.length()]); 3 } 4 public static int dfs(String s, int i, int j, int dp[][]) { 5 if(dp[i][j] != 0) {//如果已经有值,则直接返回,代表记忆性 6 return dp[i][j]; 7 } 8 if(i > j) { 9 return 0; 10 } 11 if(i == j) { 12 return 1; 13 } 14 if(s.charAt(i) == s.charAt(j)) { 15 dp[i][j] = dfs(s, i + 1, j - 1, dp) + 2; 16 } 17 else { 18 dp[i][j] = Math.max(dfs(s, i + 1, j, dp), dfs(s, i, j -1, dp)); 19 } 20 return dp[i][j]; 21 }