「这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战」
回文子串
给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。
回文字符串 是正着读和倒过来读一样的字符串。
子字符串 是字符串中的由连续字符组成的一个序列。
具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。
示例 1:
输入: s = "abc"
输出: 3
解释: 三个回文子串: "a", "b", "c"
示例 2:
输入: s = "aaa"
输出: 6
解释: 6个回文子串: "a", "a", "a", "aa", "aa", "aaa"
提示:
1 <= s.length <= 1000
s
由小写英文字母组成
暴力破解
思路
- 子串连续,是否是回文数
我们通过两次for循环来,列出所有子串的结果
这里我们用i表示子串的起点,j来表示子串的结束
i可以等于j 因为单个字符也算是一个子串
我们将每次得到的结果再用chek函数来判断是不是回文数
如果 是 则结果ans++
var check = function (s, l, r) {
while (l <= r) {
if (s[l] === s[r]) {
l++
r--
} else {
return false
}
}
return true
}
var countSubstrings = function (s) {
const n = s.length;
let ans = 0;
for (let i = 0; i < n; ++i) {
for (let j = i; j < n; ++j) {
if (check(s, i, j)) ans++
}
}
return ans;
};
中心扩展的思路
思路
我们可以列出所有的中心,并统计每个中心有几个回文串,得到最终答案
子串的中心有两种
- 子串长度为奇数,中心为一个字符
- 子串长度为偶数,中心为两个字符
这个题目中,我们可以用中心扩展的思路来解决
我们在遍历的过程中,先找到字符串s的所有子串的中心,然后用两个指针left和right分别想两侧扩展,每次left--,right++,如果s[left] === s[right]则证明符合回文子串,最终结果ans++
子串的中心有两种情况:
- 中心一个字符,那么left=right=i,然后向两边扩展
- 中心两个子串,我们这里遍历到字符串s的最后一位,所以以i为中心的右节点,即,left = i-1,right=i。然后向两边扩展
最后将所有结果相加返回ans即可
var extend = function(s,left,right){
var ans = 0;
while (left >= 0 && right <= s.length - 1 && left <= right && s[left] === s[right]) {
ans++
left = left - 1
right = right + 1
}
return ans
}
var countSubstrings = function (s) {
var n = s.length;
let ans = 0;
let left, right
for (let i = 0; i < n; ++i) {
//中心一个字符串
left = i
right = i
ans+=extend(s,left,right)
//中心两个字符串
left = i - 1
right = i
ans+=extend(s,left,right)
}
return ans;
};