题目
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:
输入:s = "cbbd"
输出:"bb"
提示:
1 <= s.length <= 1000
s 仅由数字和英文字母组成
解题思路
中心扩展法
首先要知道回文串的定义,回文串是一个正读和反读都一样的字符串,比如 aba 或者 abba,既然正读与反读都是一样,那么这个串必然有一个中心对称点,我们可以利用这个中心点向两边扩展,找出最大的回文字串。遍历字符,把当前下标作为中心点,向两边进行扩展,直到左边的字符和右边的字符不一样,当然,就像给出的样例一样,回文串有可能是偶数个数也有可能是奇数个数,所以要以偶数回文串以及奇数回文串为目标求两个回文串,然后再取较大的那个。遍历完数组后,我们就可以得到最大回文字串了。
动态规划
这种回文字串的题目是DP里面的经典题目了,递推式也很简单,我们定义dp[len][len]数组,dp[i][j]=true表示从下标i至下标j的字串是回文串,而如果想要dp[i][j]为回文串,则必须要满足dp[i+1]dp[j-1]=true && s[i]==s[j]
同样我们再考虑下边界的情况,如果i至j,只有一个字符或者只有两个字符并且两个字符相等的时候,这个时候就找到了边界条件,也就可以完成这个DP了。
AC代码
中心扩展法
点击查看代码
class Solution {
private String getStr(String s, int low, int high) {
int len = s.length();
while( low>=0 && high<len ) {
if( s.charAt(low)==s.charAt(high) ) {
low --;
high ++;
} else {
break;
}
}
return s.substring(low+1, high);
}
public String longestPalindrome(String s) {
int len = s.length();
if( len<2 ) {
return s;
}
String res = "";
for(int i=0; i<len-1; i++) {
String odd = getStr(s, i, i);
String even = getStr(s, i, i+1);
String maxStr = odd.length()>even.length()?odd:even;
if( maxStr.length() > res.length() ) {
res = maxStr;
}
}
return res;
}
}
动态规划
点击查看代码
class Solution {
public String longestPalindrome(String s) {
int len = s.length();
// 空串和只有一个字符的字符串可以直接返回
if( len < 2 ) {
return s;
}
String res = s.substring(0, 1);
boolean dp[][] = new boolean[len][len];
for(int i=0; i<len; i++) {
dp[i][i] = true;
}
char[] chars = s.toCharArray();
// 枚举最长回文串的长度
for(int k=2; k<=len; k++) {
for(int i=0; i<len; i++) {
int j = k + i - 1;
if( j>=len ) {
break;
}
if( chars[i]!=chars[j] ){
dp[i][j] = false;
continue;
}
if( j-i<=2 ) {
dp[i][j] = true;
} else {
dp[i][j] = dp[i+1][j-1];
}
if( dp[i][j] && res.length()<j-i+1 ) {
res = s.substring(i, j+1);
}
}
}
return res;
}
}