Problem
LeetCode 5. Longest Palindromic Substring
1. 题目简述
找出一个字符串的最长回文子字符串。例如:
Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.
2. 算法思路
一道经典老题目了,也不分析了,直接背答案吧,和它相似的题目还有两道,“LeetCode 516 最长回文子序列”和“LeetCode 647 回文子字符串”。
Dynamic Programming
首先,对于这种求最值的问题,第一反应就应该是DP,确实这道题是一个经典的斜着DP的题目。
我们定义dp[i][j]表示从index为i到j的子字符串是否是回文序列。
base case是当i == j时,dp[i][j] = true;对于其他的任意一对i和j,如果s[i]和s[j]相同,则只要dp[i + 1][j - 1]为true,dp[i][j]就为true,或者 j - i <= 2 也可满足要求,若 j-i == 1,则是两个相邻的字符,类似于“aa”;如果j - i == 2,则有可能是“aba”这种类型的字符串,也是回文字符串。故有如下递推式
\begin{equation}
dp[i][j] = dp[i + 1][j - 1] || j - i \leq 2 \text{ if } s[i] = s[j]
\end{equation}
\begin{equation}
dp[i][j] = false \text{ if } s[i] \neq s[j]
\end{equation}
遍历顺序根据自身喜好来,注意j是要大于i的,所以整张dp表只有一半会被遍历到。而且要注意,当计算dp[i][j]的时候,dp[i + 1][j - 1]必须是已经计算完毕的了,因此建议i从后向前计算,也就是从n - 1开始,到0。然后每次j从i + 1到n - 1.
时间复杂度为O(n ^ 2),空间复杂度也是O(n ^ 2)
中心扩散法
对于每个回文序列来说,它的特性是镜像对称的,也就是说它存在一个中心点(长度为奇数)或者中轴(长度为偶数)。
对于0到n - 1中任意一个字符i,它可能是中心点,也可能是在某中轴的左右侧。如果他是中心点,那么从i分别向左右扩散,会找到以i为中心的回文子串,直到两端或者不匹配;如果中轴刚好在它的右侧,那么从i向左和i+1向右出发(包括i和i+1),逐渐找到回文字符串。
3. 解法
Dynamic Programming bottom-up
1 |
|
中心扩散法
1 | public class Solution { |