(一)问题描述
5. 最长回文子串 - 力扣(LeetCode)5. 最长回文子串 - 给你一个字符串 s,找到 s 中最长的 回文 子串。 示例 1:输入:s = "babad"输出:"bab"解释:"aba" 同样是符合题意的答案。示例 2:输入:s = "cbbd"输出:"bb" 提示: * 1 <= s.length <= 1000 * s 仅由数字和英文字母组成https://leetcode.cn/problems/longest-palindromic-substring/description/?envType=study-plan-v2&envId=top-100-liked给你一个字符串
s
,找到 s
中最长的 回文 子串。
示例 1:
输入:s = "babad" 输出:"bab" 解释:"aba" 同样是符合题意的答案。示例 2:
输入:s = "cbbd" 输出:"bb"
提示:
1 <= s.length <= 1000
s
仅由数字和英文字母组成
(二)解决思路
这道题是用动态规划来解决的(乍一看很难想到动态规划上,但我觉得“最长”这种字眼出现了,在想不到其他方法的前提下都可以考虑是不是贪心或者动态规划)。
dp数组是布尔型数组,dp[i][j]用来表示 i 和 j 之间的子串是不是回文串。
比较容易看出的递推关系是,对于任何满足s.charAt(i)=s.charAt(j)的子串,dp[i][j]=dp[i+1][j-1],例如在abba这个回文串里dp[0][3]=dp[1][2]。这里要比较哪个回文子串的长度更长,所以比较特别的一点是遍历的是子串的长度,而非终止位置j,j是通过子串长度和起始位置i计算得到的。
class Solution {
public String longestPalindrome(String s) {
int m = s.length();
if(m<2) return s;
boolean[][] dp = new boolean[m][m];
for(int i=0;i<m;i++){
dp[i][i]=true;
}
//begin用来记录最长回文子串的起始位置
int begin=0;
int maxLen=1;
//遍历长度,用长度和起始位置i来计算终止位置j
for(int len=2;len<=m;len++){
for(int i=0;i<m;i++){
int j = len+i-1;
if(j>=m) break;
if(s.charAt(i)!=s.charAt(j)){
dp[i][j]=false;
}
else{
if(j-i<2){
dp[i][j]=true;
}else{
//当j-i<2时,这种情况会导致j-1<i+1,此时dp[i+1][j-1]不合法;
//boolean默认值为false
dp[i][j] = dp[i+1][j-1];
}
}
if(dp[i][j]&&j-i+1>maxLen){
maxLen = j-i+1;
begin = i;
}
}
}
return s.substring(begin,begin+maxLen);
}
}