2024/12/8 【哈希表】LeetCode 383.赎金信【√】知识点:all函数,ord函数,Collections.Counter,count函数,str.count函数
方法1:数组
all(...)
all
函数用于检查迭代器中的所有条件是否都为True
。- 如果任意一个条件为
False
,all
会返回False
。
方法2:使用defaultdict
我的代码:
代码随想录的代码:
方法3:使用字典
方法4:使用Counter
from collections import Counter class Solution: def canConstruct(self, ransomNote: str, magazine: str) -> bool: return not Counter(ransomNote) - Counter(magazine)
collections.Counter
Counter
是一个字典子类,用于统计字符串或其他可迭代对象中各元素的出现次数。- 它返回一个类似字典的对象,其中键是字符,值是对应字符的出现次数。
减法运算 (-
)
Counter
支持集合操作,比如减法:A - B
:生成一个新的Counter
,它保留A
中每个键的值减去B
中对应键的值的结果。- 如果某个键的结果为负或 0,则在结果中会被忽略。
Counter(ransomNote) - Counter(magazine)
:
- 计算
ransomNote
中字符是否可以被magazine
覆盖:- 如果
magazine
中某个字符不足以满足ransomNote
的需求,那么差值中会留下那些“未被满足”的字符及其所需的数量。
- 如果
方法5:使用count函数
class Solution: def canConstruct(self, ransomNote: str, magazine: str) -> bool: return all(ransomNote.count(c) <= magazine.count(c) for c in set(ransomNote))
核心逻辑
-
set(ransomNote)
:- 将
ransomNote
转换为集合。 - 这样可以去除重复字符,只保留唯一的字符,避免重复计算。
- 将
-
ransomNote.count(c)
和magazine.count(c)
:str.count(c)
是字符串的方法,用于计算字符c
在字符串中出现的次数。- 例如:
ransomNote = "aa" magazine = "ababc" print(ransomNote.count('a')) # 输出: 2 print(magazine.count('a')) # 输出: 2
-
all(...)
:all
函数返回布尔值:- 如果迭代器中所有条件都为
True
,则返回True
。 - 如果有任何一个条件为
False
,则返回False
。
- 如果迭代器中所有条件都为
效率分析
-
时间复杂度:
str.count(c)
的时间复杂度为 O(n),其中 n 是字符串的长度。- 遍历
set(ransomNote)
的字符集合,每个字符调用一次str.count
。 - 如果
ransomNote
的长度为 m,magazine
的长度为 n,最坏情况下复杂度为 O(k⋅(m+n)),其中 k 是set(ransomNote)
的大小。
-
空间复杂度:
- 使用
set(ransomNote)
需要额外的 O(k)空间。
- 使用
对比其他方法
相比使用 Counter
或数组记录字符频率,这种方法:
- 优点:
- 简洁易懂,不需要额外的数据结构。
- 缺点:
- 对于长字符串,重复调用
str.count
导致效率低下。
- 对于长字符串,重复调用
总结
这段代码通过直接比较每个字符的出现次数解决问题,逻辑清晰,但对于长字符串或重复字符较多的场景,可能性能不如基于 Counter
的实现。