题目:力扣https://leetcode-cn.com/problems/longest-palindromic-substring/
方法一:暴力解法
class Solution {
public String longestPalindrome(String s) {
String f = new String();
if(s.length()==1){
f = s;
}else{
int count = 0;
for(int i=0;i<s.length();i++){
int temp=0;
for(int j=i-1;j>0;j--){
String str = s.substring(j,i);
boolean check = checkPalindrome(str);
if(check){
temp = temp+1;
if(temp>count){
count = temp;
f = str;
}
}else{
break;
}
}
}
}
return f;
}
public boolean checkPalindrome(String s){
char[] temp = s.toCharArray();
int flag=1;
int i=0;
int j = s.length()-1;
boolean k = true;
while(flag==1){
if(i>=j){
flag = 0;
}else if(temp[i]!=temp[j]){
flag = -1;
}
i = i++;
j = j--;
if(flag==0||flag==-1){
break;
}
}
if(flag==0){
k = true;
}else if(flag==1){
k = false;
}
return k;
}
}
结果是:
上面是我第一次写的代码,写完之后一执行就被leetcode报“超出时间限制”,至于上面代码的正确性我倒也没有检验,这个方法一不是重点。这个方法思路很无脑,就是先写一个“检测是否为回文”的方法,从头到尾枚举再调用这个方法检验。提醒一下,其实是有暴力解法不超时的,但是我写的不是最简最优的暴力解法。(其实也是我不愿意在暴力解法上做优化了,于是去学习然后重新换了个思路。)
方法二:中心扩散
class Solution {
public String longestPalindrome(String s) {
if(s.length()<1){
return "";
}
int len1;
int len2;
int len;
int start=0;
int end=0;
for(int i=0;i<s.length();i++){
len1 = checkPla(s,i,i);
len2 = checkPla(s,i,i+1);
len = Math.max(len1,len2);
if(len>end-start){
start = i-(len-1)/2;
end = i+len/2;
}
}
return s.substring(start,end+1);
}
private int checkPla(String s,int left,int right) {
int L = left, R = right;
while (L>=0 && R<s.length() && s.charAt(L)==s.charAt(R)) {
L--;
R++;
}
return R-L-1;
}
}
思路:因为暴力解法的效率低,所以这里采取了中心扩散法。顾名思义,其实就是枚举“中心”可能出现的位置。回文的定义就是,在中心左右的两个字符相等,那么就可以先写一个私有的方法实现这一操作,然后再调用。具体视频如下。
最长回文子串演示
1.检查回文的方法。private表示这个方法是私有的,判断左右是否越绝,字符是否相等,若都符合要求则确定是回文,然后继续向左向右扩散,重复上述判断直至判断不合要求位置,计算其长度最后返回。
private int checkPla(String s,int left,int right) {
int L = left, R = right;
while (L>=0 && R<s.length() && s.charAt(L)==s.charAt(R)) {
L--;
R++;
}
return R-L-1;
}
2.对特殊情况的处理,增强健壮性。
if(s.length()<1){
return "";
}
3.声明各种变量。len1是“中心”在字符上时判断回文的最长长度;len2是“中心”在字符间时判断回文的最长长度;len是在i一样时,取上述两种方法所得回文长度较长的一种方法;start是表示当回文长度达到当前最长时的起始位置;end是表示当回文长度达到当前最长时的终止位置。
int len1;
int len2;
int len;
int start=0;
int end=0;
4.i在一个位置时,用len1(“中心”在字符上)与len2(“中心”在字符间)两种方法分别判断最长回文长度,len取上述两者较大者,若len大于先前记录下来的最大长度,则更新start(起始位置)和end(终止)。
for(int i=0;i<s.length();i++){
len1 = checkPla(s,i,i);
len2 = checkPla(s,i,i+1);
len = Math.max(len1,len2);
if(len>end-start){
start = i-(len-1)/2;
end = i+len/2;
}
}
5.最后返回从其实位置至终止位置的子串即可。注意下标的处理。
return s.substring(start,end+1);