5-最长回文子串

5-最长回文子串

力扣5

https://leetcode-cn.com/problems/longest-palindromic-substring/


思路

很有意思很高频的一道题,我的思路历程是这样的:

确定左右然后对区间判断? 不对—>应该是以i为中间往两边扩散

“aba”和”abba”好像不一样啊? 只是l和r初始值不能是等于i,而是相同字母的左右边界,这样两种情况就一样了

想明白了这两点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public String longestPalindrome(String s) {
if (s == null || s.length() == 0) return "";
char[] chars = s.toCharArray();
int[] idx = new int[2]; //用来存最长的结果的左右下标,不要每次都substring,这样太慢
for (int i = 0; i < chars.length; i++) {
int l = i, r = i; //从中间向两边找
//l和r初始值应该是相同字母的左右边界
while (l - 1 >= 0 && chars[l - 1] == chars[i]) l--;
while (r + 1 < chars.length && chars[r + 1] == chars[i]) r++;
while (l - 1 >= 0 && r + 1 < chars.length){
if (chars[l - 1] != chars[r + 1]){
break;
}
l--; //左右扩散
r++;
}
if ((r - l) > (idx[1] - idx[0])){
idx[0] = l;
idx[1] = r;
}
}
return s.substring(idx[0], idx[1] + 1);
}


优化

[a]代表当前遍历到了哪里

对于b[b]bbb和 bb[b]bb我们可以发现其实定位l和r的初始值后是一样的,所以我们可以跳过这几种,具体有以下两点要做

  1. 定位完r后,直接让i = r,跳过中间的所有b([b]bbbb—>bbbb[b])
  2. 这样操作后实际上没有i在中间的情况(b[b]bbb),因为我们实际上只找了最左边那次,所以可以不用再定位l,只需要定位r
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public String longestPalindrome(String s) {
if (s == null || s.length() == 0) return "";
char[] chars = s.toCharArray();
int[] idx = new int[2];
for (int i = 0; i < chars.length; i++) {
int l = i, r = i;
//while (l - 1 >= 0 && chars[l - 1] == chars[i]) l--; //优化2,实际上不需要找左边了
while (r + 1 < chars.length && chars[r + 1] == chars[i]) r++;
i = r; //优化1,跳过中间部分,直接定位到同字母的最后一个
while (l - 1 >= 0 && r + 1 < chars.length){
if (chars[l - 1] != chars[r + 1]){
break;
}
l--;
r++;
}
if ((r - l) > (idx[1] - idx[0])){
idx[0] = l;
idx[1] = r;
}
}
return s.substring(idx[0], idx[1] + 1);
}


后记,准备将原来的一些题目重做一下,有一些题目真的是感觉得出一定是高频题,比如链表反转,最长回文,最长不重复,最大子数组…接下来会重做这些题目


参考

评论区糖丶7的方法


其他字符串类型的题目可以点击这里

#
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×