题目描述
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入: s = "babad"
输出: "bab"
解释: "aba" 同样是符合题意的答案。
示例 2:
输入: s = "cbbd"
输出: "bb"
提示:
1 <= s.length <= 1000s仅由数字和英文字母组成
解题思路
采用中心扩展算法,从字符串str中的字符str[i]开始,使用两个指针left、right同时分别向左、右移动,直到str[left] != str[right]为止,记录下回文子串的长度len,进行下一轮对i的遍历,最后返回len最大的回文子串。
特别需要注意的是,由于回文子串len的长度位置,因此需要根据两种可能性进行查找:对于len为奇数的情况,起始时left == right;而对于len为偶数的情况,起始时right == left + 1。
最终代码
public String longestPalindrome(String s) {
// 排除字符串为空或长度小于2的情况
if (s == null || s.length() < 2) return s;
// 初始化最长回文子串的起始位置和长度
int resIdx = 0, resLen = 1;
// 遍历字符串,每一轮的i为中心位置
for (int i = 0; i < s.length() - 1; i++){
// 假设回文子串为奇数的情况
int len1 = longestLen(s, i, i);
// 假设回文子串为偶数的情况
int len2 = longestLen(s, i, i+1);
// 更新最长回文子串长度以及起始位置
if (len1 > resLen) {
resLen = len1;
resIdx = i - resLen / 2;
}
if (len2 > resLen) {
resLen = len2;
resIdx = i - (resLen / 2 - 1);
}
}
return s.substring(resIdx, resIdx + resLen);
}
// 根据提供的初始指针left、right查找最长回文子串长度
private int longestLen(String str, int left, int right){
// 从提供的初始指针left、right开始由中心向左右移动,直到两字符不相等
while (left >= 0 && right < str.length() && str.charAt(left) == str.charAt(right)){
left--;
right++;
}
return right - left - 1;
}