题意:
找出最长回文子序列的长度
分析:
我们首先要搞清楚什么是回文字符串,接着才能知道怎么去搜索。
什么是回文字符串呢?要求区间内互补位都相等。
那么我们怎么去搜索出一个回文字符串呢?
比如: c d b a e a f b f a d c
我们一般化的来举例,比如我们现在的搜索区间是b a e a f,这个区间里最长回文字符串的长度等于它中间三个字符构成的字符串的长度。
我们继续思考发现我们用左右界确定一个区间,那么这个区间的最大回文字符序列的长度等于:
1 若两边界left , right相等 则等于【left+1, right-1】区间的值+2
2 若两边界不相等,则等于[ left+1, right]和 [left, right - 1]区间中大的那个值
搜索树:(结点就是动态变化的内容即区间)
区间[left , right]
区间[left+1 , right-1] 区间[left+1 , right] 区间[left , right-1]
所以我们不关心其他,只关心我们的搜索区间和对应的结果值,这是我们的一般情况
以及区间动态变化对于结果值的影响,这是我们的动态变化情况。
所以解决一个问题的关键在于抓住它的什么是动态变化的。明显我们的区间是动态变化的(不仅仅是区间长度,是确定的区间位置),所以需要区间左右界来描述。
以下是递归深搜算法,但是超时(不过如果传递一个存储数据的容器在参数中不会超时),考虑改用动态规划。
public class Solution {
String s;
int len = 0;
public int longestPalindromeSubseq(String s) {
this.s = s;
return helper(0, s.length()-1);
}
private int helper(int left, int right){
if(left > right)
return 0;
if(left == right)
return 1;
if(s.charAt(left) == s.charAt(right)){
return helper(left+1, right-1)+2;
}else{
return Math.max(helper(left+1, right), helper(left, right-1));
}
}
}
深搜超时,改用动态规划:
深搜是区间动态变化,传递变化的结果值
动态规划是区间动态变化,记录变化的结果值
public class Solution {
public int longestPalindromeSubseq(String s) {
int[][] dp = new int[s.length()][s.length()];
for (int i = s.length() - 1; i >= 0; i--) {
dp[i][i] = 1;
for (int j = i+1; j < s.length(); j++) {
if (s.charAt(i) == s.charAt(j)) {
dp[i][j] = dp[i+1][j-1] + 2;
} else {
dp[i][j] = Math.max(dp[i+1][j], dp[i][j-1]);
}
}
}
return dp[0][s.length()-1];
}
}