最长回文子串
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = “babad”
输出:“bab”
解释:“aba” 同样是符合题意的答案。
示例 2:
输入:s = “cbbd”
输出:“bb”
本题有多种解法,常见的三种:
- 中心扩散法
- 马拉车算法
- 动态规划
最容易理解的中心扩散法,我们记忆这一种解法
/**
* 中心扩散法
*
* @param s
* @return
*/
private static String longestPalindrome2(String s) {
if (s == null || s.length() == 0) {
return null;
}
String ans = "";
// 回文串分为两种,奇数回文串和偶数回文串
// ababb 这个就叫奇数回文串 bab
for (int i = 1; i < s.length(); i++) {
// 奇数和偶数的主要区别,就是left的起始位置不同,一个是i-1开始,一个是i开始
int left = i - 1;
int right = i + 1;
// 判断如果是回文,从中心往两边扩散
while (left > 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
left --;
right++;
}
// 与当前的结果ans对比一下,如果大于了当前的ans,更新ans
// 这里为什么是right - left - 1
// 在纸上画一下
// 上面的例子ababb,当退出while的时候,左指针在左边的a处,右指针在最右边的b处
// 那么中间的长度是多少?长度是3对吧,那就是4-0-1=3
if (ans.length() < right - left - 1) {
// substring是左闭右开的
ans = s.substring(left + 1, right);
}
}
// 第二种就是偶数回文串
// abaabb 回文串baab就是偶数回文串
for (int i = 0; i < s.length(); i++) {
int left = i;
int right = i + 1;
while (left > 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
left --;
right++;
}
if (ans.length() < right - left - 1) {
ans = s.substring(left + 1, right);
}
}
return ans;
}
优雅版本
private static String longestPalindrome(String s) {
String res = "";
for (int i = 0; i < s.length(); i++) {
// 以 s[i] 为中心的最长回文子串
String s1 = palindrome(s, i, i);
// 以 s[i] 和 s[i+1] 为中心的最长回文子串
String s2 = palindrome(s, i, i + 1);
// res = longest(res, s1, s2)
res = res.length() > s1.length() ? res : s1;
res = res.length() > s2.length() ? res : s2;
}
return res;
}
private static String palindrome(String s, int l, int r) {
// 防止索引越界
while (l >= 0 && r < s.length() && s.charAt(l) == s.charAt(r)) {
// 双指针,向两边展开
l--; r++;
}
// 返回以 s[l] 和 s[r] 为中心的最长回文串
return s.substring(l + 1, r);
}