「这是我参与2022首次更文挑战的第8天,活动详情查看:2022首次更文挑战」
前言
每天至少一道算法题,死磕算法
今天我们继续深入字符串,看看字符串还有哪些其他的解题方法?
今天我们在说一个回文串的解题方法----中心扩散法
方法讲解
先来说说什么是中心扩散法
回文串的题我们了解不少了,我们一般都是从两边往中间去解题,而今天我们要讲解的就是从中心向两边去扩散
因此中心扩散法的思路是:遍历每一个索引,以这个索引为中心,利用“回文串”中心对称的特点,往两边扩散,看最多能扩散多远。
在这里要注意一个细节:回文串在长度为奇数和偶数的时候,“回文中心”的形式是不一样的。
- 奇数回文串的“中心”是一个具体的字符,例如:回文串
"aba"的中心是字符"b"; - 偶数回文串的“中心”是位于中间的两个字符的“空隙”,例如:回文串
"abba"的中心是两个"b"中间的那个“空隙”。
题目
给你一个字符串 s,找到 s 中最长的回文子串。
难度: 中等
示例 1:
输入: s = "babad"
输出: "bab"
解释: "aba" 同样是符合题意的答案。
第一步:从题目中提取关键字
- 1.从字符串中找到最长的回文子串
- 2.只要返回一个就行了,不用全部返回
思路
- 1.上文已经说了,我们要使用中心扩散法,因为我们的中心扩散法就专门用于这种
找回文子串的 - 2.如果字符串的length<2,那证明字符串只有一个字符,直接返回就行了
- 3.中心扩散法要遍历所有的字符
- 1.当前字符的奇数回文串
- 2.当前字符的偶数回文串
- 3.对比奇数回文串和偶数回文串结果
- 4.要写一个中心扩散函数,传入string,左指针,右指针
- 1.左边的字符等于右边的字符,left--,right++
- 2.如果不相等,则跳出循环,返回回文串
题解
var centerSpread = (str, left, right) => {
// 双指针判断条件
while (left >= 0 && right < str.length) {
if (str[left] === str[right]) {
left--;
right++;
} else {
break;
}
}
return str.substring(left + 1, right);
};
var longestPalindrome = function (s) {
// 如果s的length<2的话,那么证明就一个字符,所以直接返回就行了
let length = s.length;
if (length < 2) {
return s;
}
// 定义一个结果
let res = s.substring(0, 1);
// 初始化最大长度,用于对比for循环中的每一次长度
let maxLength = 1;
// 中心扩散法遍历的字符到length-1就可以了,否则i+1就到数组边界外了
for (let i = 0; i < length-1; i++) {
// 奇数回文串
let oddStr = centerSpread(s, i, i);
// 偶数回文串
let evenStr = centerSpread(s, i, i + 1);
let maxStr = oddStr.length > evenStr.length ? oddStr : evenStr;
if (maxStr.length > maxLength) {
maxLength = maxStr.length;
res = maxStr;
}
}
return res;
};
总结
我们在使用中心扩散法的时候,要记住两点要点
- 1.要遍历所有字符,也就是获得所有以当前这个字符扩散开的回文串
- 2.要考虑回文串是奇数还是偶数,取决于中心是一个字符,还是字符中间的空隙