题目:
Given a string s, find the longest palindromic subsequence's length in s. You may assume that the maximum length of s is 1000.
Example 1:
Input:
"bbbab"Output:
4One possible longest palindromic subsequence is "bbbb".
Example 2:
Input:
"cbbd"Output:
2One possible longest palindromic subsequence is "bb".
思路:
典型的动态规划题目。我们定义dp[i][j]表示在s[i]到s[j]之间的最长回文数的长度(约定当i > j时dp[i][j] = 0),那么状态转移方程分为两种情况:
1)当s[i] == s[j]时,s[i]和s[j]可以加入dp[i+1][j-1]的两端,所以:dp[i][j] = dp[i+1][j-1] + 2;
2)当s[i] != s[j]时,要么在回文中舍弃s[i],要么舍弃s[j],所以dp[i][j] = max(dp[i+1][j], dp[i][j - 1])(注意s[i]和s[j]同时被舍弃的情况也包含在这种情况里面了)。
所以代码就很容易写出来了。时间复杂度是O(n^3),空间复杂度是O(n^2)。
通过观察上面的代码可以发现:dp[i][j]只和dp[i+1][j-1], dp[i+1][j], dp[i][j-1]有关。所以如果我们让i从大往小循环,j从小往大循环,还可以进一步将空间复杂度从O(n^2)降低到O(n)。有兴趣的读者可以在下面代码片段的基础上进一步修改^_^。
代码:
class Solution {
public:
int longestPalindromeSubseq(string s) {
if (s.length() == 0) {
return 0;
}
vector<vector<int>> dp(s.length(), vector<int>(s.length(), 0));
for (int len = 0; len < s.length(); ++len) {
for (int i = 0; i + len < s.length(); ++i) {
int j = i + len;
if (i == j) {
dp[i][j] = 1;
}
else {
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.length() - 1];
}
};