开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 13 天,点击查看活动详情
背景
笔者最近刷了一道力扣题 最长回文串,略有所悟,分享给掘友🍺
题目
给定一个包含大写字母和小写字母的字符串 s ,返回通过这些字母构造成的 最长的回文串,在构造过程中,请注意 区分大小写 。比如 "Aa" 不能当做一个回文字符串。
示例:
输入: s = "abccccdd"
输出: 7
解释:
我们可以构造的最长的回文串是"dccaccd", 它的长度是 7。
思路
假设回文串叫p,原始字符串叫s。
偶数字符
只要是s中出现了偶数次的字符,都可以全部拿到p中,因为以p的中心点为中心,把这些偶数字符在两边等量分布,即可形成回文。
如:
abbaaacccc 形成最长回文串可以是 aaccbbccaa
aaaaaaccbb 形成最长回文串可以是 aaacbbcaaa
奇数字符
对于 奇数字符,把它减1就能得到该字符最大的偶数次数,那么就跟 偶数字符 一个逻辑了,累加上即可。
最后,如果出现过奇数字符,可以在剩余的奇数字符任意选择 1 个放在 p 的正中间,这不会影响两边已经布好的回文字符,但是注意只能选 1 个奇数字符,但凡多 1 个都会找不到字符和它匹配。
如:
aaabbcc 形成最长回文串可以是 bcaaacb
aabccde 形成最长回文串可以是 acbca
计算方法
所以,总结起来的字符计算方法就是:
偶数次字符个数 + (每种奇数次字符个数-1) * (奇数字符种类) + (出现过奇数字符 ? 1 : 0)
代码
function longestPalindrome(s: string): number {
// 统计词频
const map = new Map<string, number>();
for (let i = 0, len = s.length; i < len; i++) {
const count = map.get(s[i]);
map.set(s[i], count ? (count + 1) : 1);
}
// 遍历词频表:
// 1. 偶数词频,直接累加上
// 2. 奇数词频,减1后累加上
// 3. 如果出现了奇数,最后累加1
let showOdd = false;
let maxLen = 0;
for (let [_, value] of map) {
if (value % 2 === 0) {
maxLen += value;
}
else {
showOdd = true;
maxLen += (value - 1);
}
}
if (showOdd) {
maxLen += 1;
}
return maxLen;
};
总结
本文是笔者对 最长回文串 这道题的心得感悟,并输出了解题思路和具体的代码,文中涉及数学的 奇数偶数以及它们对回文串的影响,笔者水平有限,不对之处请掘友批评指正~
「保持学习 主动思考 坚持输出」,我是前端涤生,希望这篇文章可以帮到您🍺🍺