LeetCode刷题-字符串:最长回文串

本文介绍了三种解决LeetCode中‘最长回文串’问题的方法,包括统计字符个数并去除、利用Counter统计及用set记录奇数次字符。讨论了如何处理奇数个字符的情况,以构建最长回文串。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

给定一个包含大写字母和小写字母的字符串 s ,返回通过这些字母构造成的最长的回文串

在构造过程中,请注意 区分大小写 。比如 "Aa" 不能当做一个回文字符串。

示例1:

输入:s = "abccccdd"
输出:7
解释:
我们可以构造的最长的回文串是"dccaccd", 它的长度是 7。

示例2:

输入:s = "a"
输出:1

示例3:

输入:s = "aaaaaccc"
输出:7

提示:

  • 1 <= s.length <= 2000
  • s 只由小写 和/或 大写英文字母组成

解题思路

根据题目我们发现,构成回文串的字符对称地分布在字符串两端,因此可以确定如果某字符有偶数个,则其均可以参与构成回文串;而若某字符有奇数个,则只有一组奇数个字符是可以全部参与构成回文串的(多的那个放中间),而剩余的几组都要去掉一个字符。

法1:(执行时间36ms,内存消耗12.9MB)

首先想到的是遍历字符串,统计字符串中每个字符的个数,若该字符的个数为偶数,则直接按该字符的个数记;否则按该字符的个数-1记,同时记录字符个数为奇数的有几个。在遍历过程中,将统计过的字符去掉(可用replace()函数进行替换)。遍历完成后,当奇数个字符的个数大于等于1时,总数加一。

class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: int
        """
        sum = 0
        q_num = 0
        for i in s:
            num = s.count(i)
            if num % 2 == 0:
                sum += num
            else:
                sum += num-1
                q_num +=1
            s=s.replace(i,'')
        if q_num >= 1:
            sum += 1
        return sum

 法2:(执行时间:20ms,内存消耗12.8MB)

该方法利用collections.Counter(s)来统计某序列中每个元素出现的次数,并以键值对的方式存在字典中。但类型其实是Counter

nums = [1, 2, 3, 1, 2, 1]
counts = collections.Counter(nums)
print(counts)
## Counter({1: 3, 2: 2, 3: 1})

首先统计序列每个元素出现的次数,然后遍历其values值,针对每个字符,假设它出现了v次,那么可以使用该字符 v/2*2 次,即在回文串左侧和右侧分别放 v/2 个字符( / 为整数除法,比如‘a’出现了5次,则可以在回文串左右两边各放2个‘a’)。

接着判断如果有任一字符出现的次数v为奇数,即 v%2 == 1,那么可以把这个字符作为回文中心来放置,但需要注意的是,最多只有一个字符可以作为回文串中心。因此可以设置变量ans来存储回文串的长度,在遍历字符时,ans每次增加 v/2*2 ,故ans一直都是偶数,当出现第一个次数为奇数的字符后,将ans增加1,它就变成了奇数,后面再遇到其它奇数次的字符时,就不再改变ans的值了。故判断条件可以设置为 if ans % 2 == 0 and v%2 ==1:ans +=1

class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: int
        """
        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

法3:(执行时间:16ms,内存消耗:12.7)

用set()来创建一个空的集合,用来记录字符出现的次数(集合有自动去重的功能)。字符相同则相消,最后set留下的是不能相消的,奇数次数的字符。
如 aabcab, 最后 set 里留下的是 ac。
假如 set 为空,则说明所有的字符都出现偶数次,最长回文肯定就是s的长度。
否则,最长回文就是 s 长度 - set 长度 + 1, 即从set中取一个字符,和剩下的成偶数字符组成一个最长回文。
即 aabb,再加一个 a 或者 c,可构成最长回文。

class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: int
        """
        d = set()
        for i in s:
            if i not in d:
                d.add(i)
            else:
                d.remove(i)
        if not d:
            return len(s)
        else:
            return len(s)-len(d)+1

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值