题目:给你一个字符串s,找到s中的最长回文子串。
例子:输入:s = "babad",输出:"bab",解释:"aba"同样也是符合题意的答案。
本文使用的是中心扩散法,原理是:从当前字符开始,向两边扩散查找,找到相同的字符,说明是回文子串,不同则不是回文子串。
下面代码中有两个解法,解法二是解法一的改进版。
话不多说,直接上代码:
public class Main {
public static void main(String[] args) {
String s = "cabbs";
System.out.println(solution(s));
System.out.println(solutionPlus(s));
}
/**
* 此解法低效,原因是将单数双数的情况分开进行了存储,
* 之后再通过遍历将结果展示,使得效率非常低,第二种方法对此进行了改进
* @param s
* @return
*/
public static String solution(String s){
List<String> strList = new ArrayList<>();
for(int i = 0;i<s.length();i++){
String str = "" + s.charAt(i);
String str1 = "";
for(int j = 1;j<=i&&j<s.length()-i;j++){
if(s.charAt(i-j) == s.charAt(i+j)){
str = s.charAt(i-j)+str+s.charAt(i+j);
}else{
break;
}
}
for(int l = 0;l<=i&&l<s.length()-i-1;l++){
if(s.charAt(i-l) == s.charAt(i+l+1)){
str1 = s.charAt(i-l)+str1+s.charAt(i+l+1);
}else{
break;
}
}
strList.add(str);
strList.add(str1);
}
//最大子串索引位置
int m = 0;
//最大子串长度
int n = 0;
//记录当前索引位置
int k = 0;
for (String s1 : strList) {
if(s1.length()>n){
n = s1.length();
m = k;
}
k++;
}
return strList.get(m);
}
/**
* 基于第一种方法的改进解法
* @param s
* @return
*/
public static String solutionPlus(String s){
int maxStart = 0;
int maxLength = 0;
for(int i = 0;i<s.length();i++){
int right = i+1;
int left = i-1;
//子串长度
int length = 0;
while(left>=0){
if(s.charAt(i) == s.charAt(left)){
length++;
}else{
break;
}
left--;
}
while(right<s.length()){
if(s.charAt(i) == s.charAt(right)){
length++;
}else{
break;
}
right++;
}
while(left>=0 && right<s.length()){
if(s.charAt(left) == s.charAt(right)){
length = length + 2;
}else{
break;
}
left--;
right++;
}
if(maxLength<length){
maxLength = length;
maxStart = left+1;
}
}
return s.substring(maxStart,maxStart+maxLength+1);
}
}