[路飞]_程序员必刷力扣题: 回文子串

123 阅读1分钟

「这是我参与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++

子串的中心有两种情况:

  1. 中心一个字符,那么left=right=i,然后向两边扩展
  2. 中心两个子串,我们这里遍历到字符串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;
};