这是我参与11月更文挑战的第13天,活动详情查看:2021最后一次更文挑战」
回文子串
今天我们来看一道关于字符串的题目,回文子串。在这里我们先明确什么是回文串(回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串)。这个算法题非常有意思,对我来说是一道有点难度的题,大家一起来看一看。
LeetCode原题传送门647. 回文子串
题目
给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。
回文字符串 是正着读和倒过来读一样的字符串。
子字符串 是字符串中的由连续字符组成的一个序列。
具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。
Given a string s, return the number of palindromic substrings in it.
A string is a palindrome when it reads the same backward as forward.
A substring is a contiguous sequence of characters within the string.
Example:
Input: s = "abc"
Output: 3
Explanation: Three palindromic strings: "a", "b", "c".
Input: s = "aaa"
Output: 6
Explanation: Six palindromic strings: "a", "a", "a", "aa", "aa", "aaa".
思考线
解题思路
如果要判断一个字符串是不是回文字符串,我们可以先找到这个字符串的回文中心(回文字符串的中心字符),回文中心可能是一个字符也可能是两个字符(根据字符串的奇偶性)。
根据字符串的长度为 1, 回文中心的个数为1。
长度为2, 回文中心的个数为3(左,右,左右)
长度为3,回文中心的个数为5(左,左中,中,右中,右)
......
由此我们可以推断出长度为n的字符串会生成2n-1组回文中心。
假设回文中心为[l,r], 其中l = i/2, r = i/2 + (i%2).(这个假设是个很有灵性的假设)
这样我们只要遍历 0~ 2n-2, 就可以得到所有可能的回文中心,这样就把奇数和偶数的长度两种情况统一起来了。
根据上面的规则,当我们确定子字符串回文中心以后,我们就可以向两边推算,如果相等则是 一个子回文数,若是不相等在此回文中心下,这个字符串已经没有回文子串了。
那么这个问题的代码实现就呼之欲出了
代码实现
var countSubstrings = function(s) {
const len = s.length
let ans = 0;
for(let i = 0; i < 2 * len - 1; i ++) {
let l = Math.floor(i/2);
let r = l + i % 2;
while(l >=0 && r < len && s[l] === s[r]) {
ans ++;
l --;
r ++;
}
}
return ans;
};
总结
这个回文子字符串的问题的核心点是
- 你要想如何判断字符串是不是回文字符串 ---> 找回文中心。
- 如何找到长度为n的字符串的回文中心的通项公式。(重点,整个解法最重要的突破点)
- 如何让奇数和偶数的回文中心统一起来。(难点,难以想象出这个点,第一个想出的人肯定体会到了灵光乍现的爽快)
好了这就是今天的刷题内容,我们明天见。