Problem
LeetCode 516. Longest Palindromic Subsequence
1. 题目简述
找出一个字符串的最长回文子序列。例如:
Example 1:
Input:
"bbbab"
Output:
4
One possible longest palindromic subsequence is "bbbb".
2. 算法思路
和它相似的题目还有两道,LeetCode 5 最长回文子字符串和LeetCode 647 回文子字符串。
这里我们要注意,这里是子序列,而不是子字符串,子字符串是要求连续的,而子序列不是。
Dynamic Programming
对于求子序列的题目,而且还是最大值的,我们第一反应肯定还是DP,思路和 LeetCode 5 最长回文子字符串 不同的是,dp策略有所改变。
我们回忆一下,对于5,我们只考虑dp[i][j]的时候,如果s[i] == s[j],需要考虑dp[i + 1][j - 1]是否是回文字符串,dp[i][j]表示i到j是否是回文子字符串;那么对于这道题来说,如果s[i] == s[j],则需要将dp[i + 1][j - 1] + 2,其中dp[i][j]表示i到j的最长回文子序列的长度。
那么如果s[i] != s[j]时,对于5来说,dp[i][j]直接为false;而对于本题来说,是一个int值,dp[i][j] = max(dp[i + 1][j], dp[i][j - 1])。
base case的情况是dp[i][i] = 1,不需要考虑j - i之类的,因,如果对于j - i = 2的case来说,dp[i + 1][j - 1] = dp[i + 1][i + 1] = 1,可以正常计算的,不受影响;如果 j - i = 1,那么说明两个数挨着,dp[i + 1][j - 1]看似是不合法的,但实际上是0,直接加2也是OK的,所以边界情况无需再考虑。
所以递推式如下
\begin{equation}
dp[i][j] = dp[i + 1][j - 1] + 2 \text{ if } s[i] = s[j]
\end{equation}
\begin{equation}
dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]) \text{ if } s[i] \neq s[j]
\end{equation}
遍历顺序依旧按照自身喜好来,但是这里依然是和5做同样选择,因为递推式的前项依赖的需求。
时间复杂度为O(n ^ 2),空间复杂度也是O(n ^ 2)
补充
这里用中心扩散法就明显行不通了,因为是非连续的,怎么扩散嘛,没辙。
3. 解法
Dynamic Programming bottom-up
1 |
|