暴力解法(Java)
class Solution {
public String longestPalindrome(String s) {
int len = s.length();
if (len < 2) {
return s;
}
int maxLen = 1;
int begin = 0;
char[] charArray = s.toCharArray();
// 枚举所有长度大于 1 的子串 charArray[i..j]
for (int i = 0; i < len - 1; i++) {
for (int j = i + 1; j < len; j++) {
if (j - i + 1 > maxLen && validPalindromic(charArray, i, j)) {
maxLen = j - i + 1;
begin = i;
}
}
}
return s.substring(begin, begin + maxLen);
}
//验证子串 s[left..right] 是否为回文串
private boolean validPalindromic(char[] charArray, int left, int right) {
while (left < right) {
if (charArray[left] != charArray[right]) {
return false;
}
left++;
right--;
}
return true;
}
}
动态规划解法(Java)
class Solution {
public String longestPalindrome(String s) {
int len = s.length();//字符串s的长度
int maxLen = 1;//最长的回文子串的长度
int begin = 0;//最长的回文子串的左边界
char[] charArray = s.toCharArray();//字符串转为字符数组,便于判断回文串
boolean[][] dp = new boolean[len][len];//dp[i][j]表示s[i..j]是否回文串
//字符串长度为1都是回文串(题目规定1 <= s.length <= 1000,故下述for可省略)
for(int i = 0; i < len; i++)
dp[i][i] = true;
for(int L = 2; L <= len; L++){
//回文子串的左边界
for(int i = 0; i < len; i++){
int j = L + i - 1;//回文子串的右边界
if(j >= len)//右边界超出字符串长度
break;
if(charArray[i] != charArray[j])//首尾字符不同
dp[i][j] = false;
else{//首尾字符相同
if((j - i) < 3)//子串长度为2或3时,首尾字符相同必为回文串
dp[i][j] = true;
else//P(i,j)=P(i+1,j−1)
dp[i][j] = dp[i + 1][j - 1];
}
//s[i..j]是回文串且长度更长
if(dp[i][j] && (j - i + 1) > maxLen){
maxLen = j - i + 1;
begin = i;
}
}
}
return s.substring(begin, begin + maxLen);
}
}
中心扩散解法(Java)
核心思想:回文串的中心只有两种情况,其一是中间只有一个字符,其二是中间有两个相同字符,在此基础上向边界扩散,只要扩散边界的两个字符不相同,则该字符串不是回文串(注意边界的越界判断)。
class Solution {
public String longestPalindrome(String s) {
int len = s.length();//字符串s的长度
int start = 0, end = 0;//回文子串的边界
for(int i = 0; i < len; i++){
int len1 = extend(s, i, i);//中间只有一个字符
int len2 = extend(s, i, i + 1);//中间有两个相同字符
int maxLen = Math.max(len1, len2);//取其较大长度
//子串长度更长
if(maxLen > (end - start + 1)){
start = i - (maxLen - 1) / 2;//定位最长回文子串的左边界
end = i + maxLen / 2;//定位最长回文子串的右边界
}
}
return s.substring(start, end + 1);
}
//由回文串的中心向边界扩散
public int extend(String s, int left, int right){
//扩散条件:左边界不越界且右边界不越界且左、右边界的字符相同
while(left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)){
left--;
right++;
}
return right - left - 1;//计算当前回文子串的长度
}
}