題目連接:https://leetcode.com/problems/longest-palindromic-subsequence/description/數組
題目大意:找出最長迴文子序列(不連續),第5題是最長迴文子串。ide
法一(借鑑):dp,與5題,最長迴文子串進行比較,這個dp更難一點。代碼以下(耗時51ms):spa
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):code
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]中。blog
dp數組填充順序:從下向上,每次計算都使用左邊、下邊,左下的數據。ip
法二(借鑑):記憶性搜索,其實感受仍是dp的思想,可是會比純dp快。代碼以下(耗時39ms):leetcode
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 }