简介
题目链接:https://leetcode.cn/problems/longest-palindromic-substring/description/
解决方式:字符串 + 暴力枚举 / 中心扩展法(双指针)
暴力枚举
实现思路:
双重循环暴力枚举,枚举每一个可能的字符串,判断其是否是回文子串,是则进行下一步与全局维护的最大回文子串进行对比,实时更新最大回文子串。
java
class Solution {
public String longestPalindrome(String s) {
int n = s.length();
int maxLen = 0;
int start = 0; // 记录最长回文子串的起始索引
// 枚举所有子串的起始位置
for (int i = 0; i < n; i++) {
// 枚举所有子串的结束位置
for (int j = i; j < n; j++) {
if (isPalindrome(s, i, j)) {
int len = j - i + 1;
if (len > maxLen) {
maxLen = len;
start = i;
}
}
}
}
return s.substring(start, start + maxLen);
}
// 判断子串 s[i..j] 是否为回文串
private boolean isPalindrome(String s, int left, int right) {
while (left < right) {
if (s.charAt(left) != s.charAt(right)) {
return false;
}
left++;
right--;
}
return true;
}
}
中心扩展法
实现思路:
回文子串会有中心点,可能是一个(奇数)也可能是两个(偶数)。我们可以迭代所有可能的中心点,判断当前中心点是否是回文子串,然后由中心点周围扩展。同时维护一个全局最大回文子串,迭代的每一个回文子串都与全局最大进行对比,实时更新全局最大回文子串。
java
class Solution {
public String longestPalindrome(String s) {
int n = s.length();
// 全局最长回文子串(左闭右开)
int maxLeft = 0;
int maxRight = 0;
// 迭代所有可能的中心点
for(int center = 0; center < 2*n-1; center++){
// 初始化双指针指向奇数或偶数中心
int left = center / 2;
int right = (center + 1) / 2;
// 扩展回文子串,直到双指针指向回文子串边界的外侧
while(left >= 0 && right < n && s.charAt(left) == s.charAt(right)){
right++;
left--;
}
// 比较该回文子串与全局最大回文子串
if(right - left - 1 > maxRight - maxLeft){
// 更新最大回文子串
maxLeft = left + 1;
maxRight = right;
}
}
// 返回结果
return s.substring(maxLeft, maxRight);
}
}
另一种写法
java
class Solution {
public String longestPalindrome(String s) {
int n = s.length();
// 全局最长回文子串(左闭右开)
int maxLeft = 0;
int maxRight = 0;
// 迭代所有可能的中心点
for(int i = 0; i < n; i++){
// 初始化双指针指向奇数中心
int left = i;
int right = i;
// 扩展回文子串,直到双指针指向回文子串边界的外侧
while(left >= 0 && right < n && s.charAt(left) == s.charAt(right)){
right++;
left--;
}
// 比较该回文子串与全局最大回文子串
if(right - left - 1 > maxRight - maxLeft){
// 更新最大回文子串
maxLeft = left + 1;
maxRight = right;
}
// 初始化双指针指向偶数中心
left = i;
right = i + 1;
// 扩展回文子串,直到双指针指向回文子串边界的外侧
while(left >= 0 && right < n && s.charAt(left) == s.charAt(right)){
right++;
left--;
}
// 比较该回文子串与全局最大回文子串
if(right - left - 1 > maxRight - maxLeft){
// 更新最大回文子串
maxLeft = left + 1;
maxRight = right;
}
}
// 返回结果
return s.substring(maxLeft, maxRight);
}
}