声明:
今天是第91道题。给定一个包含大写字母和小写字母的字符串,找到可由这些字母构造成的最长的回文串。以下所有代码经过楼主验证都能在LeetCode上执行成功,代码也是借鉴别人的,在文末会附上参考的博客链接,如果侵犯了博主的相关权益,请联系我删除
(手动比心ღ( ´・ᴗ・` ))
正文
题目:给定一个包含大写字母和小写字母的字符串,找到可由这些字母构造成的最长的回文串。在构造过程中,请注意区分大小写。比如 "Aa"
不能当做一个回文字符串。
注意:
假设字符串的长度不会超过 1010。
示例 1:
输入: "abccccdd" 输出: 7 解释: 我们可以构造的最长的回文串是"dccaccd", 它的长度是 7
解法1。观察得知,构成回文串肯定是由偶数字符和1个奇数字符构成的,所以只要计算出s里有几个出现频次为奇数的字符,然后用s的长度减去奇数字符个数再加1(减去了频次为奇数的字符剩下都是偶数次的字符了,奇数字符也变偶数字符了),考虑一种特殊情况,如果全是偶数字符就直接返回s的长度,代码如下。
执行用时: 48 ms, 在Longest Palindrome的Python3提交中击败了94.29% 的用户
- 偶数字符:毋庸置疑,肯定可以都出现在最长回文串里
- 奇数字符:奇数字符频数-1后变为偶数字符放到回文串里,最后还可以再加上1个奇数字符放中间
class Solution:
def longestPalindrome(self, s):
"""
:type s: str
:rtype: int
"""
odd_cnt = 0
for i in set(i): # 注意这里一定要去重,避免重复计数
if s.count(i) % 2 != 0:
odd_cnt += 1
if odd_cnt == 0:
return len(s)
return len(s)-odd_cnt+1 # 奇数字符频次都-1,累加起来就是-odd_cnt,最后+1是还能从减去的这些奇数字符里挑1个出来放中间
# 上述代码的优化版本
count = 0
for i in set(s):
if s.count(i) % 2 == 0:
count += s.count(i)
else:
count += (s.count(i)//2)*2 # 此处很妙,奇数字符的频次若>2的话,通过除2取余再乘2可以保留欧偶数个字符
if res < len(s):
res += 1
return res
解法2。大致思路和上面差不多,就是用了字典统计出每个字符的出现频数并分为奇数和偶数,然后返回最长回文串的长度,代码如下。
执行用时: 64 ms, 在Longest Palindrome的Python3提交中击败了22.50% 的用户
class Solution:
def longestPalindrome(self, s):
"""
:type s: str
:rtype: int
"""
from collections import Counter
dict_s = Counter(s)
even = []
odd = []
for k,v in dict_s.items():
if v%2 == 0:
even.append(v)
else:
odd.append(v)
if len(odd) != 0: # 也就是说s里面有奇数字符
max_odd = max(odd)
odd.remove(max_odd)
return max_odd + sum(even) + sum(odd) - len(odd)
else:
return sum(even)
结尾
解法1:https://www.jianshu.com/p/ebdd12da8c3c
解法2:LeetCode