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:
4
One possible longest palindromic subsequence is "bbbb".
Example 2:
Input:
"cbbd"
Output:
2
One possible longest palindromic subsequence is "bb".
這道題給了我們一個字符串,讓我們求最大的回文子序列,子序列和子字符串不同,不需要連續。而關於回文串的題之前也做了不少,處理方法上就是老老實實的兩兩比較吧。像這種有關極值的問題,最應該優先考慮的就是貪婪算法和動態規划,這道題顯然使用DP更加合適。我們建立一個二維的DP數組,其中dp[i][j]表示[i,j]區間內的字符串的最長回文子序列,那么對於遞推公式我們分析一下,如果s[i]==s[j],那么i和j就可以增加2個回文串的長度,我們知道中間dp[i + 1][j - 1]的值,那么其加上2就是dp[i][j]的值。如果s[i] != s[j],那么我們可以去掉i或j其中的一個字符,然后比較兩種情況下所剩的字符串誰dp值大,就賦給dp[i][j],那么遞推公式如下:
/ dp[i + 1][j - 1] + 2 if (s[i] == s[j])
dp[i][j] =
\ max(dp[i + 1][j], dp[i][j - 1]) if (s[i] != s[j])
解法一:
class Solution { public: int longestPalindromeSubseq(string s) { int n = s.size(); vector<vector<int>> dp(n, vector<int>(n)); for (int i = n - 1; i >= 0; --i) { dp[i][i] = 1; for (int j = i + 1; j < n; ++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][n - 1]; } };
我們可以對空間進行優化,只用一個一維的dp數組,參見代碼如下:
解法二:
class Solution { public: int longestPalindromeSubseq(string s) { int n = s.size(), res = 0; vector<int> dp(n, 1); for (int i = n - 1; i >= 0; --i) { int len = 0; for (int j = i + 1; j < n; ++j) { int t = dp[j]; if (s[i] == s[j]) { dp[j] = len + 2; } len = max(len, t); } } for (int num : dp) res = max(res, num); return res; } };
下面是遞歸形式的解法,memo數組這里起到了一個緩存已經計算過了的結果,這樣能提高運算效率,使其不會TLE,參見代碼如下:
解法三:
class Solution { public: int longestPalindromeSubseq(string s) { int n = s.size(); vector<vector<int>> memo(n, vector<int>(n, -1)); return helper(s, 0, n - 1, memo); } int helper(string& s, int i, int j, vector<vector<int>>& memo) { if (memo[i][j] != -1) return memo[i][j]; if (i > j) return 0; if (i == j) return 1; if (s[i] == s[j]) { memo[i][j] = helper(s, i + 1, j - 1, memo) + 2; } else { memo[i][j] = max(helper(s, i + 1, j, memo), helper(s, i, j - 1, memo)); } return memo[i][j]; } };
類似題目:
參考資料:
https://discuss.leetcode.com/topic/78603/straight-forward-java-dp-solution
https://discuss.leetcode.com/topic/78799/c-beats-100-dp-solution-o-n-2-time-o-n-space