最长回文串
Category | Difficulty | Likes | Dislikes |
---|---|---|---|
algorithms | Easy (49.37%) | 62 | - |
Tags
Companies
在构造过程中,请注意区分大小写。比如 "Aa"
不能当做一个回文字符串。
注意: 假设字符串的长度不会超过 1010。
示例 1:
输入:
"abccccdd"
输出:
7
解释:
我们可以构造的最长的回文串是"dccaccd", 它的长度是 7。
1
回文是前后读起来都一样
那么如果这个回文字符串是偶数的话
那就是对称的,aaabbxxbbaaa
如果我们那把每个字母的个数统计起来
比如
字母a
的len
就是6
字母b
的len
就是4
字母x
的len
就是2
那回文的长度就是 每个字母的len
累积
即,6+4+2
但是如果
字母a
的len
就是7
即长度是奇数
能在回文中添加的长度据
parseInt(len/2)*2
这里使用parseInt()
比如aaa
的长度就是3
parseInt(3/2)*2 === 2
这样我们就知道
在回文长度是偶数的情况下
回文的总长度是字母的parseInt(len/2)*2
累积
那如果回文长度是奇数的话
我们就可以随意的在中间添加一个多出来的字母
比如,``aaabbxoxbbaaa`
当我们在求最长的时候
我们一般尽可能的是要奇数的
所以当我们原本的长度是偶数
即ret % 2 === 0
我们还有多出来的字母
比如任意某个字母的
len % 2 === 1
我们就可以给re++
思路清楚后
我们第一个遇到的问题就是
如何计算每个字母的次数
这里我们利用charCodeAt
可以把字母转换为数字
比如
console.log('a'.charCodeAt()); // 97
console.log('A'.charCodeAt()); // 65
console.log('z'.charCodeAt()); // 122
console.log('Z'.charCodeAt()); // 90
那我们把这数字作为数组的下标,那么该下标的值做为字母次数
let count = Array(128).fill(0)
for (const c of s) {
count[c.charCodeAt()]++
}
这里使用128的长度是因为,简单的ASCII表示0到127
我们当然可以取的更低,但是需要知道映射,挺麻烦的,简单取128就可以了
我们使用一个ret
来记录回文长度
let ret = 0
for (const len of count) {
if (len !== 0) {
ret += parseInt(len / 2) * 2
if (len % 2 === 1 && ret % 2 === 0) {
ret++
}
}
}
最终的代码就是
/*
* @lc app=leetcode.cn id=409 lang=javascript
*
* [409] 最长回文串
*/
/**
* @param {string} s
* @return {number}
*/
var longestPalindrome = function (s) {
let count = Array(128).fill(0)
for (const c of s) {
count[c.charCodeAt()]++
}
let ret = 0
for (const item of count) {
if (item !== 0) {
ret += parseInt(item / 2) * 2
if (item % 2 === 1 && ret % 2 === 0) {
ret++
}
}
}
return ret
};
复杂度分析
时间复杂度:
n为 s 的长度,至少遍历每个字符一次。
空间复杂度:
我们需要开辟额外空间来计数,其大小为 s 中字母的个数,我们都知道字母最多为26个。