1. 题目
给定一个字符串,判断该字符串中是否可以通过重新排列组合,形成一个回文字符串。
1.1 示例
-
示例 1 1 1 :
- 输入:
s = "code"; - 输出:
False。
- 输入:
-
示例 2 2 2 :
- 输入:
s = "aab"; - 输出:
True。
- 输入:
-
示例 3 3 3 :
- 输入:
s = "carerac"; - 输出:
True。
- 输入:
1.2 说明
- 来源: 力扣(LeetCode)
- 链接: https://leetcode-cn.com/problems/palindrome-permutation
2. 解法一
2.1 分析
如果一个字符串可以组成一个回文串,那么:
- 如果它的长度为偶数,那么每个字符都必须出现偶数次;
- 如果它的长度为奇数,那么除了一个字符出现奇数次以外,其它的字符都必须出现偶数次。
因此可以总结得到,如果一个字符串可以组成一个回文串,那么出现奇数次的字符的数量不能超过 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 个。
本文探讨了如何利用Python判断字符串是否能通过重新排列组成回文串,提供了Counter和集合两种方法,并分析了它们的时间和空间复杂度。
1367

被折叠的 条评论
为什么被折叠?



