本题也是中等题中做的不熟的,主要需要掌握三种做法:
1.暴力,枚举所有的子串,并对所有的子串进行validate,那么时间复杂度是O(n^3)
2.枚举中心,然后向两边扩展,计算当前中心的最大回文子串长度:时间复杂度是O(n^2)
class Solution {
private int len;
private char[] c;
// 返回以c1,c2为下标的中心对应的回文串的最大长度
private int helper(int c1,int c2){
int l=c1==c2?1:2;
while((--c1>=0)&&(++c2<len)){
if(c[c1]!=c[c2]){
break;
}
l+=2;
}
return l;
}
public String longestPalindrome(String s) {
if(s==null||s.length()==0){
return s;
}
len=s.length();
c=s.toCharArray();
int max=1;
int start=0;
for(int i=0;i<len-1;i++){
int oddlen=helper(i,i);
int evenLen=c[i]==c[i+1]?helper(i,i+1):0;
if(oddlen>max){
start=i-oddlen/2;
max=oddlen;
}
if(evenLen>max){
start=i-evenLen/2+1;
max=evenLen;
}
}
return s.substring(start,start+max);
}
}
写代码时遇到一个问题:明明错乱,比如两个变量,一个用来保存字符串的长度,一个用来保存当前回文子串的长度,我竟然都命名为len,这种bug一定要避免,一般来说,变量名的长度应该根据作用域的大小来设置,越大,越长
3.dp:递推关系,如果一个子串[i,j]是回文串,并且s[i-1]==s[j+1],那么[i-1,j+1]也是回文子串
这里使用dp[i][j]来表示[i,j]是否是回文子串,因为i<=j,所以我们要填的就是一个上三角,并且主对角线上因为代表单个字符的字符串,所以都是回文串.此外,我们要保证dp[i][j]在dp[i-1][j+1]之前计算,即填表应该是行从大到小,列从小到大
当然本题dp的性能并不比2好,同样的O(n^2)的时间复杂度,空间却是O(n^2)
class Solution {
public String longestPalindrome(String s) {
if(s==null||s.length()==0){
return s;
}
int len=s.length();
char[] c=s.toCharArray();
boolean[][] dp=new boolean[len][len];
int max=1;
int start=0;
for(int j=0;j<len;j++){
for(int i=j;i>=0;i--){
if(i==j){
dp[i][j]=true;
}else{
if((j-i)==1){
dp[i][j]=c[i]==c[j];
}else{
dp[i][j]=dp[i+1][j-1]&&c[i]==c[j];
}
}
if(dp[i][j]&&(j-i+1)>max){
max=j-i+1;
start=i;
}
}
}
return s.substring(start,start+max);
}
}