LeetCode地址,以及本文主要参考了LeetCode的官方解答
比较简单的方法就是遍历所有的子串,然后判断这个子串是不是回文串.是的话就再判断长度,比已经搜索到的长,就记录下来.返回结果就好.一开始会觉得遍历的方法会怪怪的,但后来发现自己想多了.很好遍历.双层循环嵌套就好.第一层为开始字符的指针进行遍历,后面则遍历起始位置剩下的所有位置即可.
public static String longestPalindrome(String s) {
String res ="";
int n = s.length();
for(int i=0;i<n;i++){
for(int j=i;j<=n;j++){
if(j-i+1<=res.length())continue;
String temp = s.substring(i,j);
boolean flag = true;
for(int k=0;k<temp.length()/2;k++){
if(temp.charAt(k)!=temp.charAt(temp.length()-1-k)){
flag = false;
break;
}
}
if(flag)res = temp;
}
}
return res;
}
算法的时间复杂度是O(n^3)
然后就是第一次真正实践的动态规划dp
其实说起来很简单,我不用公式进行说明.动态规划局就是找到一个递推公式,进行结果的判断.
比如这道题:我判断一个长度为五的字符串是不是回文,我只需要判断两头字母是否相等,以及去掉两头的字母是否还是回文.如果都是那就是回文.(推到最后就是一个字母,和两个字母的情况)所以我们从一个字母开始,到两个字母…整个字符串.这样就能算出所有子串是否为回文了.
public String longestPalindrome(String s) {
String res ="";
int n = s.length();
boolean[][] dp = new boolean[n][n];
for(int k=0;k<n;k++){
for(int i=0;i+k<n;i++){
int j = i + k;
if(k == 0){
dp[i][j]=true;
}
else if(k==1){
dp[i][j]= s.charAt(i)==s.charAt(j);
}
else{
dp[i][j] = (s.charAt(i)==s.charAt(j)) && dp[i-1][j-1];
}
if(dp[i][j]&&k+1>res.length())res = s.substring(i,j+1);
}
}
return res;
}
时间复杂度是O(n^2)
然后是中心拓展法.其实我觉得也是暴力遍历法,不过遍历的方式比较巧妙.第一个方法遍历的字母是以那个字母为边界进行判断.而中心拓展法则是以字母作为中心进行遍历.我们遍历到一个字母以后,就向这个字母两边伸展开进行判断伸展以后的字符串是否是回文,如果是的话就继续伸展,不是的话就返回最长的伸展.因为后面也不可能是回文了(注意判断边界>=0,<=n)
然后还需要注意考虑的一点是,可能是一个字母为中心,可能是两个字母为中心,这个处理方法很巧妙,就是扩展的索引是都是从i开始和从i 和 i+1开始的区别.
public String longestPalindrome3(String s) {
int start=0,end=0;
int n = s.length();
for(int i=0;i<n;i++){
int len1 = expands(s,i,i);
int len2 = expands(s,i,i+1);
int len = Math.max(len1,len2);
if(end-start+1<len){
start = i - (len-1)/2;
end = i + len/2;
}
}
return s.substring(start,end+1);
}
public int expands(String s,int left,int right){
int n = s.length();
while (left>=0&&right<n&&s.charAt(left)==s.charAt(right)){
left--;
right++;
}
return right-left-1;
}
复杂度是O(n^2)