echo

任生命穿梭 时间的角落

0%

回文子串

647. 回文子串

给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。

具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。

示例 1:

1
2
3
输入:"abc"
输出:3
解释:三个回文子串: "a", "b", "c"

示例 2:

1
2
3
输入:"aaa"
输出:6
解释:6个回文子串: "a", "a", "a", "aa", "aa", "aaa"

提示:

  • 输入的字符串长度不会超过 1000 。

我们枚举每一个可能的回文中心,然后用两个指针分别向左右两边拓展,当两个指针指向的元素相同时就拓展,否则就停止拓展。

当回文长度为奇数时,回文中心就是一个字符;当回文长度为偶数时,回文中心为两个字符。一个长度为 n 的字符串,可能的回文中心有 2n - 1 个。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution {
public int countSubstrings(String s) {
int count = 0, n = s.length();
for(int index = 0; index < n; index++){
//回文长度为奇数
for(int j = index, k = index; j >= 0 && k < n; j--, k++){
if(s.charAt(j) == s.charAt(k)){
++count;
}else{
break;
}
}
//回文长度为偶数
for(int j = index, k = index + 1; j >= 0 && k < n; j--, k++){
if(s.charAt(j) == s.charAt(k)){
++count;
}else{
break;
}
}
}
return count;
}
}

我们可以将回文长度为奇数和偶数的两种情况合在一起,我们令 0 <= index < 2n - 1,回文中心(j, k),其中j = index / 2, k = j + (index mod 2)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public int countSubstrings(String s) {
int count = 0, n = s.length();
for(int index = 0; index < 2 * n - 1; index++){
for(int j = index / 2, k = index / 2 + index % 2; j >= 0 && k < n; j--, k++){
if(s.charAt(j) == s.charAt(k)){
++count;
}else{
break;
}
}
}
return count;
}
}

时间复杂度O(n^2),空间复杂度O(1)。