5.最长回文子串
给你一个字符串 s
,找到 s
中最长的回文子串。
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案
输入:s = "cbbd"
输出:"bb"
提示:
1 <= s.length <= 1000
s
仅由数字和英文字母组成
来源:力扣(LeetCode) 链接:力扣
//低阶版
//暴力破解法
//两个for循环遍历字符串,将所有子字符串都进行判断,如果是回文字符串,则比较长度,保留最长的
class Solution {
public String longestPalindrome(String s) {
String s1="";
int max = 0;
for (int i = 0;i<s.length();i++){
for (int j = i+1;j<s.length()+1;j++){
if (isPalindrome(s.substring(i,j))){
if (max < (j-i)){
max = j-i;
s1 = s.substring(i,j);
}
}
}
}
return s1;
}
//判断是否是回文字符串
public boolean isPalindrome(String s){
int i = 0,j=s.length()-1,c = s.length()/2;
boolean flag = true;
while (c>0){
if (s.charAt(i)!=s.charAt(j)){
flag=false;break;
}
i++;
j--;
c--;
}
return flag;
}
}
//进阶版
//一个for循环遍历字符串,从第二个字符一直遍历到最后一个字符,对比条件再判断回文长度
class Solution {
public String longestPalindrome(String s){
int max = 1;
String s1 = s.charAt(0)+"";//如果没有长度大于等于2的回文串,则返回首字母
int mid1 = 0,mid2 = 0;
for (int i=1;i<s.length();i++){
int j =i;
mid1 = i;
//例:sabbad,这里遍历到了第二个b,并且前一个字符也是b;
//所以初步判断这里有长度>=2的回文串;
//调用twoisPalindrome方法,获取以bb为中心的回文串
if (s.charAt(j-1)==s.charAt(j)){
mid2 = j-1;
String lon = twoisPalindrome(s,mid2,mid1);
if (s1.length()<lon.length()){
s1 = lon;
}
}
//如果已经遍历到了最后一个字符,后面的判断就不必要了,直接跳出循环
if ((j+1)>=s.length())break;
//例:sabbad,这里遍历到了第一个b,并且后一个字符也是b;
//所以初步判断这里有长度>=2的回文串;
//调用twoisPalindrome方法,获取以bb为中心的回文串
if (s.charAt(j+1)==s.charAt(j)){
mid2=j+1;
String lon = twoisPalindrome(s,mid1,mid2);
if (s1.length()<lon.length()){
s1 = lon;
}
}
//例:sabcbad,这里遍历到了c,并且前后字符都是b;
//所以初步判断这里有长度>=3的回文串;
//调用twoisPalindrome方法,获取以bcb为中心的回文串
if (s.charAt(j-1)==s.charAt(j+1)){
String lon = twoisPalindrome(s,j-1,j+1);
if (s1.length()<lon.length()){
s1 = lon;
}
}
}
return s1;
}
//以两端下标为mid1,mid2的字符串为中心,向两边同时扩展,获取回文串
public String twoisPalindrome(String s ,int mid1, int mid2){
String s1 = s.charAt(mid1)+""+s.charAt(mid2);
int k = 0;
while ((mid1-k)>=0&&(mid2+k)<s.length()){
if (s.charAt(mid1-k)!=s.charAt(mid2+k)){
break;
}
k++;
}
k--;
s1 = s.substring((mid1-k),(mid2+k+1));
return s1;
}
}
//高阶版
//递归查找
class Solution {
public String longestPalindrome(String s) {
char[] chs=s.toCharArray();
//max[0]最大回文串长度,max[1]最大回文串左下标,max[2]最大回文串右下标
int[] max=new int[3];
//从字符串中间向两边寻找,因为中间如果找到特别长的,两边就没必要寻找了
find(chs,chs.length/2,max,0);
return s.substring(max[1],max[2]+1);
}
//dr代表寻找方向,<=0向左,>=0向右
public void find(char[] chs,int i,int[] max,int dr){
int len=Math.max(len(chs,i,i+1),len(chs,i-1,i+1));
if(len>=max[0]){
max[0]=len;
max[1]=i-len/2+(len+1)%2;
max[2]=i+len/2;
}
//如果左侧长度可能找到大于等于当前最大串的,则继续向左找
if((i-1)*2+1>=max[0]&&dr<=0){
find(chs,i-1,max,-1);//向左递归
}
//如果右侧长度可能找到大于当前最大串的,则继续向右找
if((chs.length-i-2)*2+1>max[0]&&dr>=0){
find(chs,i+1,max,1);//向右递归
}
}
//计算最大回文串长度
public int len(char[] chs,int l,int r){
while(l>=0&&r<chs.length&&chs[l]==chs[r]){
l--;
r++;
}
return r-l-1;
}
}