力扣T5
最长回文子串
给你一个字符串 s,找到 s 中最长的回文子串。
如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:
输入:s = "cbbd"
输出:"bb"
提示:
1 <= s.length <= 1000
s 仅由数字和英文字母组成
首先这道题目拿起来就没有思路,不知道是使用什么数据结构来完成这道题。
然后就想着,既然没有思路,那么我作为一个人,是怎么判断这个子串是回文子串呢?
我这种方法是否可以用编程语言表现出来?
首先,我判断一个子串是不是回文子串是通过对称!
先找到一个元素,并以其为中心,观察左右是否对称。然后就注意到,对称有两种情况,第一种就是我一开始所想的,其特点是子串个数为奇数,第二种是子串个数为偶数。
那么先参试着把情况分为三种,第一种是偶数对称,第二种是奇数对称,第三种是不对称,
我们先遍历数组,以当前的元素作为中心,验证两边是否对称。
既然没有明确的知道这个方法行不行,不妨先把偶数的情况写出来,写完后就会发现,似乎可以正确运行,那么就先用仅有偶数对称的情况“例如aa”测试一下,结果可行,那么再另外写一个奇数的情况。
详细过程已经备注再代码里(因为边思考参试,所以就写在代码行内)
代码如下:
/**
* 给你一个字符串 s,找到 s 中最长的回文子串。
*
* 如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。
*/
publicclassT4 {
publicstaticvoidmain(String[] args) {
Strings="babad";
System.out.println(longestPalindrome(s));
}
publicstaticStringlongestPalindrome(Strings) {
//将字符串转化为数组
char[] arr=s.toCharArray();
if(arr.length<2){
returns;
}
//记录答案数组的长度
char[] ans=null;
intl=0;
//对称有两种情况,一种是个数为偶数的对称,一种是个数为奇数的对称
//偶数对称:随便找一个数,以它为中心的左元素,判断是否和右边的右元素相同,
// 是的话,那么可以明确一点的就是这两个元素可以组成长度为2的回文字串
// 在此基础上,我们要进行的是继续探索回文字串是否能再长一点,是的话就再探索
// 提出探索的条件是:某一边已经没有元素,或者是左边元素 !=右边元素
// 退出探索的时候,需要进行一个判断——判断本次探索的回文子串的长度是否大于已记录的回文子串的长度
// 是的话,那么将答案换成本次探索的字串
// 否的话,进行下一个中心位置的探索
//奇数对称:随便找一个元素,以它为中心元素,判断它左边的元素和右边的元素是否相等
// 是的话,那么就可以知道他是一个至少长度为3的回文子串
// 在此基础上继续探索
// 退出探索的条件:某一边没有元素或者 出现元素不等的情况
// 退出探索的操作如上偶数操作
for (inti=0; i<arr.length-1; i++) {
//当前元素进行判断是偶数对称还是奇数对称还是不对称
//假如是偶数对称
if (arr[i] ==arr[i+1]) {//在这里 i+1 不会出现空指针异常,因为遍历长度仅到 arr.length -1
//d表示移动步长
intd=0;
//循环,测试长度是否能增加2,这里的d 表示移动步长
while (i-d>=0&&i+1+d<arr.length){
if(arr[i-d] ==arr[i+1+d]){
d++;
}else {
break;
}
}
d--;
//判断长度是否大于已经记录的答案长度
if(2*d+2>l){
ans=getArr(arr,i-d,i+d+1);
l=2*d+2;
}
}
//假如是奇数对称
if (i-1>=0&&arr[i-1] ==arr[i+1]) {//左右对称
intd=1;
while (i-d>=0&&i+d<arr.length){
if(arr[i-d] ==arr[i+d]){
d++;
}else {
break;
}
}
d--;
if(2*d+1>l){
ans=getArr(arr,i-d,i+d);
l=2*d+1;
}
}
//没有发现回文字符,继续下一个的寻找
}
if(ans==null){
ans=getArr(arr,0,0);
}
returnString.valueOf(ans);
}
//根据下标截取数组
privatestaticchar[] getArr(char[] arr, inthead, intlast){
char[] a=newchar[last+1-head];
intb=0;
for (inti=head; i<=last; i++) {
a[b++] =arr[i];
}
returna;
}
}
因为奇数偶数的步长不一样,所以目前没法合并