2024/12/8 【哈希表】LeetCode 383.赎金信【√】知识点:all函数,ord函数,Collections.Counter,count函数,str.count函数

383. 赎金信 - 力扣(LeetCode)

代码随想录

方法1:数组

all(...)

  • all 函数用于检查迭代器中的所有条件是否都为 True
  • 如果任意一个条件为 Falseall 会返回 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

效率分析

  1. 时间复杂度:

    • str.count(c) 的时间复杂度为 O(n),其中 n 是字符串的长度。
    • 遍历 set(ransomNote) 的字符集合,每个字符调用一次 str.count
    • 如果 ransomNote 的长度为 m,magazine 的长度为 n,最坏情况下复杂度为 O(k⋅(m+n)),其中 k 是 set(ransomNote) 的大小。
  2. 空间复杂度:

    • 使用 set(ransomNote) 需要额外的 O(k)空间。

对比其他方法

相比使用 Counter 或数组记录字符频率,这种方法:

  • 优点:
    • 简洁易懂,不需要额外的数据结构。
  • 缺点:
    • 对于长字符串,重复调用 str.count 导致效率低下。

总结

这段代码通过直接比较每个字符的出现次数解决问题,逻辑清晰,但对于长字符串或重复字符较多的场景,可能性能不如基于 Counter 的实现。

posted @ 2024-12-13 09:48  axuu  阅读(4)  评论(0编辑  收藏  举报