算法题2
要求:
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
PS:
解题方法多样,本文只介绍其中的中心拓展法。
题目来源于 : 力扣(LeetCode)
本文章思路同样来源于力扣(LeetCode)文末附有力扣网址
思路:
- 中心拓展
回文字符串永远都是两边向中间走,字符对应相同,反向思考一下:从中间向两边扩散,对应位置的字符是一样的。把从中间开始扩散的字符称为——拓展中心。
/*ABBCBBD 长度为奇数的最长回文子串有单一的拓展中心就是最中间的一个字符‘C’
ABBCCBBD 长度为偶数的最长回文子串有两个拓展中心,最中间的两个字符‘C’和‘C’*/
- 确定中心和以中心向两边扩散的找子串方法
方法:用一个while循环直到两边的字符不相等时跳出循环,然后返回子串长度
public int expandAroundCenter(String s, int left, int right) {
/*输入串和左、右指针*/
int L = left, R = right;
while (L >= 0 && R < s.length() && s.charAt(L) == s.charAt(R)) {
// 情况1 单数长度:例如 a d f g f d c
//情况2 双数长度:例如: a d f g g f d c
L--;
R++;//向两边扩散
}/*1:用了在减,最后退出循环的时候 left指向的是a right 指向的是c、 所以计算长度的是 6-0-1=5*/
/*2:lift指向的是a 0位置right 指向的是c 7号位置 len长度为7-0-1=6 为什么要减1? 因为下标从0开始的。*/
return R - L - 1;//返回子串长度
}
利用一个for循环,从最开始到最末尾,由于我们要找的就是最长的回文子串,所以每个字符都可以作为我们的扩展中心找一遍然后记录长度(len)。
for(int i=0;i<s.length;i++){/*把每个字符都当做中心,遍历一次,寻找最长的回文子串*/
/*记录奇数长度回文子串*/
int lentwo=expandAroundCenter(st, i, i);
/*记录偶数长度回文子串*/
int lenone=expandAroundCenter(st, i, i+1);
/*java的Math函数,max是比较函数,输出较大的那个数*/
int len=Math.max(lenone, lentwo);
}
对比每次记录的子串的长度,返回最长的一个值,并且记录下来当前位置的回文子串的起始位置(start)和截止位置(end)
-
找出最长串
判断条件:
if(len>end-start){/*判断是否是最长的,如果是就记录当前下标。PS:第一次的时候要记录一次*/
start = i - (len - 1) / 2;//开始下标
end = i + len / 2;//结尾下标
}
- 返回最长子串
return st.substring(start, end+1);
PS:substring有两种用法:
String s="0123456";
s.substring(3);//3456 抛掉前面三个字符,输出剩下的
s.substring(3,6);//345 只输出中间的6-3个字符,起始位置是3
所以我们此处要输出完整回文串就要将末尾下标+1
代码实现如下:
static String ezmaxstr(String st){
char []s=st.toCharArray();
if(st==null||st.length()<1){
return "";
}
int start=0,end=0;
for(int i=0;i<s.length;i++){
int lentwo=expandAroundCenter(st, i, i);
int lenone=expandAroundCenter(st, i, i+1);
int len=Math.max(lenone, lentwo);
if(len>end-start){
start = i - (len - 1) / 2;
end = i + len / 2;
}
}
return st.substring(start, end+1);
}
static int expandAroundCenter(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;
}