题目描述
给你一个字符串 s,找到 s 中最长的回文子串。
-
示例 1:
输入:s = “babad”
输出:“bab”
解释:“aba” 同样是符合题意的答案。 -
示例 2:
输入:s = “cbbd”
输出:“bb” -
示例 3:
输入:s = “a”
输出:“a” -
示例 4:
输入:s = “ac”
输出:“a”
提示:
1 <= s.length <= 1000
s 仅由数字和英文字母(大写和/或小写)组成
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-palindromic-substring
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
从字符串下标为1的位置对字符进行逐个遍历,此时有两种情况
- 当前字符和前一个字符一致
- 当前字符和前前一个字符一致
出现这两种情况都可以用双指针进行回文判断,左指针和右指针同步向左/右移动,如果“左指针-右指针+1”大于当前最大回文子串的长度,就记录下左右指针的位置,方便最后调用substring()方法
代码详解
class Solution {
public String longestPalindrome(String s) {
int max = 1; // 最长回文子串长度,初始值为1
int mid = 0; // 左右指针的相对中心的一个节点
int left = 0; // 记录左指针
int right = 0; // 记录右指针
for(int i = 1; i < s.length(); ++i) { // 开始对字符串的字符进行遍历
int count = 0; // 左右指针向左/右移动的距离
if(s.charAt(i) == s.charAt(i-1)) { // 第一种情况:当前字符与前一字符一致
mid = i - 1; // 双指针的中间位置
int p = mid - count; // 临时左指针
int q = mid + count + 1; // 临时右指针
while(p >= 0 && q < s.length()) { // 左右指针不能出界
if(s.charAt(p) == s.charAt(q)) {
++count;
p = mid - count;
q = mid + count + 1;
} else {
break;
}
}
// 上述循环造成p多减1,q多加1,弥补回来
++p;
--q;
// 若长度更长,记录左右指针的位置
if(max < q - p + 1) {
left = p;
right = q;
max = right - left + 1;
}
}
if(i > 1 && s.charAt(i) == s.charAt(i - 2)) { // 第二种情况:当前字符与前前一字符一致
// 类比第一种情况,仅作微调
mid = i - 1;
int p = mid - count;
int q = mid + count;
while(p >= 0 && q < s.length()) {
if(s.charAt(p) == s.charAt(q)) {
++count;
p = mid - count;
q = mid + count;
} else {
break;
}
}
++p;
--q;
if(max < q - p + 1) {
left = p;
right = q;
max = right - left + 1;
}
}
}
return s.substring(left, right+1); // 利用记录的左右指针的位置返回子串
}
}
注意点
- 注意左右节点(包括临时的左右节点)在使用时别越界就好