给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
- 输入:s = "babad"
- 输出:"bab"
- 解释:"aba" 同样是符合题意的答案。
示例 2:
- 输入:s = "cbbd"
- 输出:"bb"
示例 3:
- 输入:s = "a"
- 输出:"a"
示例 4:
- 输入:s = "ac"
- 输出:"a"
提示:
1 <= s.length <= 1000
s 仅由数字和英文字母(大写和/或小写)组成
解题思路:
回文子串的解法有多重:
- 暴力解
- 动态规划
- 中心扩散
- Manacher 算法
这里使用的是中心扩散,比较好理解,时间复杂度也可以接受
回文子串的特性就是从左向右遍历和从右向左遍历完全一致,也就是具有对称性
根据对称性,从一点向左右扩散,那左右都是相等的
中心点有2种情况:
1.奇数回文串,中心点在子串中
2.偶数回文串,中心点不在子串中
找到,当前位置的最大回文子串,然后计算回文串的起始位置。
start = i - 左半部分 一半长度max /2 ,偶数,i不是中心点 ,左半部分为:(max-1)/2
end = i + 右半部分
class Solution {
public String longestPalindrome(String s) {
if(s==null||s.length()<=1) return s;
int start=0;int end = 0;
// 遍历查找s中的回文子串
for(int i=0;i<s.length();i++){
// 奇数数的回文串
int maxOdd = palindrome(s,i,i);
// 偶数的回文串
int maxEven = palindrome(s,i,i+1);
int max = Math.max(maxOdd,maxEven);
// 找到左右两侧的坐标
if(max>end - start){
// b a b a d
// s i max =3 start =0 end = 2;
start = i - (max - 1)/2;
end = i + max/2;
}
}
return s.substring(start,end+1);
}
// 回文子串,说明从某一中点,两侧的字符串相等
public int palindrome(String s,int left,int right){
// 边界条件,left大于左边界 ,right小于右边界
while(left>=0 && right<s.length()){
// left==right 说明是回文串,继续向两边扩展
if(s.charAt(left)==s.charAt(right)){
left--;
right++;
continue;
}
break;
}
// left,right多扩展了一次,因此长度为right-left+1 - 2
return right - left - 1;
}
}