题目描述
给定一个字符串,你的任务是计算这个字符串中有多少个回文字串。
- 具有不同开始位置或者结束位置的字串,即使是由相同的字符组成,也会被视作不同的子串。
- 回文字符串 是正着读和倒过来读一样的字符串。
- 子字符串 是字符串中的由连续字符组成的一个序列。
- 具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。
示例1
输入:'abc'
输出:3
解释:三个回文子串:'a','b','c'
示例2
输入:'aaa'
输出:6
解释:6个回文子串:'a','a','a','aa','aa','aaa'
提示:输入的字符串长度不超过1000
解法一:暴力法
let countSubStrings = function(s){
let count = 0
for(let i=0;i<s.length;i++){
for(let j=i;j<s.length;j++){
// 判断是否是回文子串
if(isPalindrome(s.substring(i, j+1))){
count++
}
}
}
return count
}
// 回文串首尾字符相同,且剩余子串也是一个回文串
let isPalindrome = function(s){
let i=0,j=s.length-1
while(i<j){
if(s[i] != s[j]) return false
i++
j--
}
return true
}
复杂度分析:
- 时间复杂度:O(n^3)
- 空间复杂度O(1)
解法:动态规划
1、分析题意
一个字符串是回文串,它的首尾字符相同,且剩余子串也是一个回文串。
其中剩余子串是否为回文串是一个子问题,它的结果影响大问题的结果。
如何来描述子问题呢?
显然,一个子串由两端的子i\j指针确定,就是描述子问题的变量,子串si...j是否是回文串,就是子问题。
let countSubstrings = function(s){
const len = s.length
let count = 0
const dp = new Array(len)
for(let j=0;j<len;j++){
for(let i=0;i<=j;i++){
// 表示竖表已经走完
if(s[i] = s[j] && (j-i<=1 || dp[i+1])){
dp[i] = true
count++
}else{
dp[i] = false
}
}
}
return count
}
复杂度分析:
- 时间复杂度:O(n^2)
- 空间复杂度O(n)