题目描述
给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串。
在构造过程中,请注意区分大小写。比如 “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