本文最后更新于589 天前,其中的信息可能已经过时,如有错误请发送邮件到tomding1065@gmail.com
https://programmercarl.com/0516.%E6%9C%80%E9%95%BF%E5%9B%9E%E6%96%87%E5%AD%90%E5%BA%8F%E5%88%97.html
1.本题求的是子序列,子序列不要求元素连续,所以本题定义的dp数组为:dp[i][j]:字符串s在[i, j]范围内最长的回文子序列的长度为dp[i][j]。递归公式的关键点还是在于要判断元素的相等情况,相等就将中间的元素基础上加上这个两个元素,不相等就就分别判断前面的元素加中间的元素的情况和中间元素加最后元素的情况取最大值即可。思路很简单。但是
在这个题中我认为最重要的是要判断清楚元素的下标的问题还有>= <=号的使用的到底是有没有=,还有创建数组的时候什么情况下应该是+ 1时候情况下是应该.size(),还有最后的结果应该是取哪一个值,需要对于自己对于的dp数组的含义有深刻的认识还有对于递归公式有清晰的认识,总之思路固然重要但是题中的小细节要注意好,像是本题我根本没有考虑到i j相等的情况我以为像上一个题一样交给递归公式处理即可,本题递归公式处理不到这个情况,而且这个情况是单个元素的情况是基础情况,我不手动初始化本题的递归公式没有办法去做其他的处理,上一个题求子串的分成三个情况,分别讨论的,在条件判断中就将i j相等的情况解决了,我觉得这样的子序列,子字符串的题,动态规划的题要多做,产生相对应的条件反射即可。所以这些题我要多刷几遍,在这个动态规划的最后进行一个我的总结,这段时间的刷题让我收获颇多,真的让我真正进入到编程的世界,我想这就是计算机的魅力吧。希望等我二刷,三刷的时候,我能够轻而易举的将每一个小细节和思路都完美处理。
CPP
class Solution {
public:
int longestPalindromeSubseq(string s) {
vector<vector<int>> dp(s.size(), vector<int>(s.size(), 0));
for(int i = 0; i < s.size(); i++)dp[i][i] = 1;
for(int i = s.size() - 1; i >= 0; i--){
for(int j = i + 1; j < s.size(); j++){
if(s[i] == s[j]){
dp[i][j] = dp[i + 1][j - 1] + 2;
}else{
dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);
}
}
}
return dp[0][s.size() - 1];
}
};