题目描述
给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串。
在构造过程中,请注意区分大小写。比如 “Aa” 不能当做一个回文字符串。
注意:
假设字符串的长度不会超过 1010。
示例 1:
输入:
"abccccdd"
输出:
7
解释:
我们可以构造的最长的回文串是"dccaccd", 它的长度是 7。
解法一:
解题思路:凡是偶数个全加上,奇数那就加上最大的偶数,最后根据是否有奇数判断加一
import collections
class Solution:
def longestPalindrome(self, s: str) -> int:
dic=collections.Counter(s)
length=0
maximum=0
for i in dic.values():
if i%2==0:
length+=i
else:
length+=i-1
maximum=1
return length+maximum
解法二:
建一个字典,字母出现次数大于等于2的,取其最大的偶数;偶数和等于字符串长度的则返回字符串,否则返回偶数和+1
class Solution:
def longestPalindrome(self, s: str) -> int:
dct = {}
ans = 0
for ch in s:
if ch not in dct:
dct[ch] = 1
else:
dct[ch] += 1
if dct[ch]==2:
dct[ch] = 0
ans += 2
return ans if ans==len(s) else ans+1
解法三
解题思路:
组回文字符串的过程,其实我们可以看作是从一个中心往旁边对称放字符的过程。
首先我们先把给的字符串统计词频
(1)对于所有的出现偶数次的字符,那么其实在组回文字符串的时候就是可以看作直接放置在中心两侧,因此有多少就直接加上去多少就好了。
(2)对于所有的出现奇数次的字符,那么实际上我们就可以看作是1 + 偶数次,偶数次统统可以加上去,剩下的都是单个的不同的字符,选一个作为中心就好了。
要注意的是,如果给的字符串全是偶数次,那么肯定中心就不会一个单一的字符,所以要加一个判断,如果出现了有字符是奇数次那么就+1,否则对于全是偶数次的字符,就不需要加1了。
class Solution:
def longestPalindrome(self, s: str) -> int:
#统计字符词频
s_cnt = collections.Counter(s)
center = 0
res = 0
for char in s_cnt:
#判断各个字符的词频奇偶
if s_cnt[char] % 2:
center = 1 #若出现奇数频次,center置为1
res += s_cnt[char] - 1
else:
res += s_cnt[char]
return res + center
解法四:
思路:
回文串是一个正着读和反着读都一样的字符串。以回文中心为分界线,对于回文串中左侧的字符 ch,在右侧对称的位置也会出现同样的字符。例如在字符串 “abba” 中,回文中心是 “ab|ba” 中竖线的位置,而在字符串 “abcba” 中,回文中心是 “ab©ba” 中的字符 “c” 本身。我们可以发现,在一个回文串中,只有最多一个字符出现了奇数次,其余的字符都出现偶数次。
那么我们如何通过给定的字符构造一个回文串呢?我们可以将每个字符使用偶数次,使得它们根据回文中心对称。在这之后,如果有剩余的字符,我们可以再取出一个,作为回文中心。
class Solution:
def longestPalindrome(self, s):
ans = 0
count = collections.Counter(s)
for v in count.values():
ans += v // 2 * 2
if ans % 2 == 0 and v % 2 == 1:
ans += 1
return ans