647. 回文子串

647. 回文子串

题目链接:647. 回文子串(中等)

给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。

回文字符串 是正着读和倒过来读一样的字符串。

子字符串 是字符串中的由连续字符组成的一个序列。

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

示例 1:

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

示例 2:

输入:s = "aaa"
输出:6
解释:6个回文子串: "a", "a", "a", "aa", "aa", "aaa"

提示:

  • 1 <= s.length <= 1000

  • s 由小写英文字母组成

解题思路

双指针

找到中心,然后往两边扩散比较。

在遍历中心的时候,中心有两种情况:一是以一个元素为中心,二是以两个元素为中心。

(注意:三个元素为中心就相当于以一个元素,然后向左右两边扩散一位)

C++

// 双指针
class Solution {
public:
    int countSubstrings(string s) {
        int result = 0;
        for (int i = 0; i < s.size(); i++) {
            result += extend(s, i, i);
            result += extend(s, i, i + 1);
        }
        return result;
    }
​
    int extend(string s, int i, int j) {
        int result = 0;
        while (i >= 0 && j < s.size() && s[i] == s[j]) {
            result++;
            i--;
            j++;
        }
       return result;
    }
};

JavaScript

/**
 * @param {string} s
 * @return {number}
 */
var countSubstrings = function(s) {
    let result = 0;
    for (let i = 0; i < s.length; i++) {
        result += extend(s, i, i);
        result += extend(s, i, i + 1);
    }
    return result;
};
​
function extend(s, i, j) {
    let result = 0;
    while (i >= 0 && j < s.length && s[i] === s[j]) {
        result++;
        i--;
        j++;
    }
    return result;
}
  • 时间复杂度:O(n^2)

  • 空间复杂度:O(1)

动态规划

  1. dp数组的含义

    dp[i][j]表示在S字符串中下标ij(包括i,ji>=j)之间的子串是否是回文。

  2. 递推公式

    • s[i] != s[j]时,那么dp[i][j] = false

    • s[i] == s[j]时,有两种种情况

      • 下标ij(包括ij)之间的子串的长度为12,那么dp[i][j] = true

      • 下标ij(包括ij)之间的子串的长度大于等于3,那么dp[i][j]的值取决于dp[i+1][j-1])(即分布向左边和右边收缩一位)。

  3. dp数组的初始化

    dp[i][j]初始化为false

  4. 遍历顺序

    从递推公式来看,dp[i][j]的值取决于dp[i+1][j-1],那么在求dp[i][j]之前必须知道dp[i+1][j-1]。所以遍历顺序为:从下到上,从左到右

C++

// 动态规划
class Solution {
public:
    int countSubstrings(string s) {
        vector<vector<bool>> dp(s.size(), vector<bool>(s.size(), false));
        int result = 0;
        for (int i = s.size() - 1; i >= 0; i--) {
            for (int j = i; j < s.size(); j++) {
                if (s[i] == s[j]) {
                    if (j - i <= 1) {
                        dp[i][j] = true;
                        result++;
                    } else if (dp[i + 1][j - 1]){
                        dp[i][j] = true;
                        result++;
                        
                    }
                }
            }
        }
        return result;
    }
};

JavaScript

/**
 * @param {string} s
 * @return {number}
 */
var countSubstrings = function(s) {
    const dp = new Array(s.length).fill().map(item => Array(s.length).fill(false));
    let result = 0;
    for (let i = s.length - 1; i >= 0; i--) {
        for (let j = i; j < s.length; j++) {
            if (s[i] === s[j]) {
                if (j - i <= 1) {
                    result++;
                    dp[i][j] = true;
                } else if (dp[i + 1][j - 1]) {
                    result++;
                    dp[i][j] = true;
                }
            }
        }
    }
    return result;
};
  • 时间复杂度:O(n^2)

  • 空间复杂度:O(n^2)

posted @ 2022-03-21 16:21  wltree  阅读(34)  评论(0编辑  收藏  举报