Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.
三种思路,一种是dp,一种是逐个延伸对称检测,还有一种比较高级的Manacher算法.
首先dp,这个我觉得是除了暴力解法之外比较容易想到的一种,我们另开一个boolean类型的二维数组,记录从i到j是否为回文数组,这样当我们在进行长度+2的判断的时候就不需要重新计算一遍,只需要计算i-1和j+1处索引的字符是否相等就可以了,代码:
public String longestPalindrome1(String s) { int len=s.length(); if(len==0) return ""; int max=1; int beginindex=0; int endindex=0; boolean[][] isPalindrome=new boolean[len][len]; for(int i=0;i<len;i++) isPalindrome[i][i]=true; for(int i=0;i<len-1;i++){ if(s.charAt(i)==s.charAt(i+1)) { isPalindrome[i][i + 1] = true; beginindex=i; endindex=i+1; } } for(int length=3;length<=len;length++){ for(int i=0;i+length-1<len;i++){ if(s.charAt(i)==s.charAt(i+length-1)&&isPalindrome[i+1][i+length-2]){ endindex=i+length-1; beginindex=i; isPalindrome[i][i+length-1]=true; } } } return s.substring(beginindex,endindex+1); }dp的时间复杂度和空间复杂度都是O(n^2)
第二种方法是时间复杂度O(n^2),空间复杂度O(1)的算法,算法本身思想很简单,从长度为n的字符串的2n-1个点出发向两侧延伸,取其中长度最长的字符串,为什么是2n-1呢,举个例子很容易明白 abba 我们分别需要从a ab之间 b bb之间 b ba之间 a这七个点进行延伸,代码:
public String longestPalindrome(String s) { int len=s.length(); if(len<=1) return s; int maxlength=0; String maxstring=""; for(int i=0;i<len-1;i++){ String s1=getMaxString(s,i,i); if(s1.length()>maxlength){ maxlength=s1.length(); maxstring=s1; } String s2=getMaxString(s,i,i+1); if(s2.length()>maxlength){ maxlength=s2.length(); maxstring=s2; } } return maxstring; } public String getMaxString(String s,int begin,int end){ int len=s.length(); while(begin>=0&&end<len&&s.charAt(begin)==s.charAt(end)){ begin--; end++; } return s.substring(begin+1,end); }第三个算法解释起来较为复杂,http://www.cnblogs.com/bitzhuwei/p/Longest-Palindromic-Substring-Part-II.html博主解释的非常清晰,建议大家有兴趣一定要看一看,这道题作为面试题的频率比较高,如果能拿出这个算法装个逼感觉还是挺爽的~我这里就贴下代码:
public String longestPalindrome(String s) {
String temp="";
for(int i=0;i<s.length();i++){
temp=temp+"#"+s.charAt(i);
}
temp+="#";
int[] length=new int[temp.length()];
int C=0,R=0;
for(int i=1;i<temp.length();i++){
int mir=2*C-i;
int dif=R-i;
if(dif>=0){
if(length[mir]<dif) length[i]=length[mir];
else{
length[i]=dif;
while(i+length[i]+1<length.length&&i-length[i]-1>=0&&temp.charAt(i+length[i]+1)==temp.charAt(i-length[i]-1)){
length[i]++;
}
C=i;
R=i+length[i];
}
}
else{
length[i]=0;
while(i+length[i]+1<length.length&&i-length[i]-1>=0&&temp.charAt(i+length[i]+1)==temp.charAt(i-length[i]-1)){
length[i]++;
}
R=i+length[i];
C=i;
}
}
int max=-1,index=0;
for(int i=0;i<length.length;i++){
if(length[i]>max){
max=length[i];
index=i;
}
}
return s.substring((index-max)/2,(index+max)/2);
}