【LeetCode 266 哈希映射】回文排列

本文探讨了如何利用Python判断字符串是否能通过重新排列组成回文串,提供了Counter和集合两种方法,并分析了它们的时间和空间复杂度。

1. 题目

给定一个字符串,判断该字符串中是否可以通过重新排列组合,形成一个回文字符串。

1.1 示例

  • 示例 1 1 1

    • 输入: s = "code"
    • 输出: False
  • 示例 2 2 2

    • 输入: s = "aab"
    • 输出: True
  • 示例 3 3 3

    • 输入: s = "carerac"
    • 输出: True

1.2 说明

2. 解法一

2.1 分析

如果一个字符串可以组成一个回文串,那么:

  1. 如果它的长度为偶数,那么每个字符都必须出现偶数次;
  2. 如果它的长度为奇数,那么除了一个字符出现奇数次以外,其它的字符都必须出现偶数次。

因此可以总结得到,如果一个字符串可以组成一个回文串,那么出现奇数次的字符的数量不能超过 1 1 1

由此,可以先统计出字符串中每个字符出现的频次,然后判断出现奇数次的字符数量是否超过 1 1 1 ,如果是则不能组成一个回文串,否则即可以组成回文串。

实际上,Python 的 collections 模块中有一个字典类 dict 的子类 Counter ,该类可以很容易的统计可迭代对象中每一个元素的频次,关于其用法可以参考【源码共读】Python 标准模块 collections 中 Counter 类详解

2.2 解答

from collections import Counter


class Solution:
    def can_permute_palindrome(self, s: str) -> bool:
        num = 0
        counter = Counter(s)
        for key in counter.keys():
            num += counter[key] % 2
            if num > 1:
                return False
        return True


def main():
    sln = Solution()
    print(sln.can_permute_palindrome('code'))  # False
    print(sln.can_permute_palindrome('carerac'))  # True
    print(sln.can_permute_palindrome('aaa'))  # True


if __name__ == '__main__':
    main()

2.3 复杂度

  • 时间复杂度: O ( ∣ S ∣ ) O(\left|S\right|) O(S)。需要遍历整个字符串以及映射表,但映射表的大小一定不会大于字符串的长度,因此时间复杂度为 O ( ∣ S ∣ ) O(\left|S\right|) O(S)
  • 空间复杂度: O ( min ⁡ { ∣ S ∣ , 128 } ) O(\min\{|S|, 128\}) O(min{S,128})。在最坏的情况下,字符串中的每一个字符都不相同,但不同的字符数目最多只有 128 128 128 个。

3. 解法二

3.1 分析

也可以使用集合来实现。集合里存放出现了奇数次的字符,具体地,在对字符串进行遍历时,如果字符 c 在集合中,就把它删除,否则就把它添加进集合中。在遍历完整个字符串后,集合的大小就表示字符串中出现奇数次的字符的数目。

3.2 解答

class Solution:
    def can_permute_palindrome(self, s: str) -> bool:
        s_set = set()
        for c in s:
            if c not in s_set:
                s_set.add(c)
            else:
                s_set.remove(c)
        return len(s_set) <= 1

3.3 复杂度

  • 时间复杂度: O ( ∣ S ∣ ) O(\left|S\right|) O(S)。需要遍历整个字符串以及映射表,但映射表的大小一定不会大于字符串的长度,因此时间复杂度为 O ( ∣ S ∣ ) O(\left|S\right|) O(S)
  • 空间复杂度: O ( min ⁡ { ∣ S ∣ , 128 } ) O(\min\{|S|, 128\}) O(min{S,128})。在最坏的情况下,字符串中的每一个字符都不相同,但不同的字符数目最多只有 128 128 128 个。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值