题目链接:
给你一个字符串 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)
动态规划
-
dp数组的含义
dp[i][j]
表示在S
字符串中下标i
到j
(包括i
,j
且i>=j
)之间的子串是否是回文。 -
递推公式
-
当
s[i] != s[j]
时,那么dp[i][j] = false
-
当
s[i] == s[j]
时,有两种种情况-
下标
i
到j
(包括i
和j
)之间的子串的长度为1
或2
,那么dp[i][j] = true
-
下标
i
到j
(包括i
和j
)之间的子串的长度大于等于3
,那么dp[i][j]
的值取决于dp[i+1][j-1]
)(即分布向左边和右边收缩一位)。
-
-
-
dp数组的初始化
dp[i][j]
初始化为false
。 -
遍历顺序
从递推公式来看,
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)
-