leetcode 383. Ransom Note

本文详细解析了LeetCode上的第383题“赎金信”问题,介绍了如何判断一个字符串是否能由另一个字符串中的字符构成,并提供了三种不同实现方式的Python代码示例。

Python leetcode

leetcode  383. Ransom Note

Given an arbitrary ransom note string and another string containing letters from all the magazines, write a function that will return true if the ransom note can be constructed from the magazines ; otherwise, it will return false.

Each letter in the magazine string can only be used once in your ransom note.


这个题目理解起来比较难,我说的意思是英语不咋滴,有些单词不太明白,怎么还有ransomNote勒索信,杂志什么的?

网上看到一个这样的理解,我们要去分别一个信是不是通过杂志里面的文字造出来的,就和侦探中的破解密码一样,可能勒索信中的字是来自杂志的,这样组合就是勒索信息。这样大概理解一些了吧。


所以说白了,就是判断ransomNote中的字符满足两个条件1.ransomNote中的字符必须在magazine中出现2.ransomNote中的字符出现次数必须不超过magazine中对应的字符次数。


Note:
You may assume that both strings contain only lowercase letters.

canConstruct("a", "b") -> false
canConstruct("aa", "ab") -> false
canConstruct("aa", "aab") -> true



题目的意思:

题目的意思是第一个的字符串的每个字符必须在第二个字符串中,且第一个字符串中的字符次数小于第二个字符串中该字符的次数。


#coding=utf-8
class Solution():
    def canConstruct(self, ransomNote, magazine):#192ms
        from collections import Counter
        magDict=Counter(magazine)
        for letter in ransomNote:
            if letter not in magDict:
                return False
            else:
                magDict[letter]=magDict[letter]-1
                if  magDict[letter]<0:
                    return False
        return True

    def canConstruct1(self, ransomNote, magazine):#184ms
        from collections import Counter
        ranDict=Counter(ransomNote)
        magDict=Counter(magazine)
        for x in ranDict:
            if x not in magDict or ranDict[x]>magDict[x]:
                return False
        return True

    def canConstruct2(self, ransomNote, magazine):  #36ms
        from collections import  Counter
        return not Counter(ransomNote)-Counter(magazine)
    #Counter()的减法结果是前者中计数大于后者中,包括不存在后者中的
    #说白了就是相对于后者多的部分,就是前者中后者没有的或少的
    #若没有的话,就返回一个空的Counter()

s=Solution()
print s.canConstruct1('aabbbsd','aaabbbbwkskhd')



你的代码实现了一个经典的“赎金信”问题(LeetCode 383. Ransom Note),判断是否可以用 `magazine` 中的字符构造出 `ransomNote`。整体逻辑是正确的,使用了哈希表统计字符频次,然后逐个匹配。 下面是对你代码的详细分析和优化建议: --- ### ✅ 原始代码分析 ```python class Solution: def canConstruct(self, ransomNote: str, magazine: str) -> bool: Dict = {} for i in range(len(magazine)): if magazine[i] in Dict: Dict[magazine[i]] += 1 else: Dict.update({magazine[i]: 1}) for i in ransomNote: if i in Dict and Dict[i] > 0: Dict[i] -= 1 else: return False return True ``` #### ✔️ 正确性: - 使用字典 `Dict` 统计 `magazine` 中每个字符出现的次数。 - 遍历 `ransomNote` 的每个字符,检查是否还有可用字符(存在且数量 > 0)。 - 如果有,则消耗一个;否则返回 `False`。 - 最终能遍历完就返回 `True`。 ✅ 功能上完全正确。 --- #### ❌ 可改进点: 1. **变量命名不规范**:`Dict` 不符合 Python 的命名规范(应小写如 `char_count`)。 2. **循环方式不够简洁**: - 第一个循环用 `for i in range(len(magazine))` 获取索引,但只用了 `magazine[i]`,不如直接遍历字符。 3. **初始化方式冗余**:可以用 `dict.get()` 或 `collections.Counter` 更简洁地完成计数。 4. **可读性和效率提升空间**:Python 提供了更优雅的方式。 --- ### ✅ 优化版本(推荐) ```python from collections import Counter class Solution: def canConstruct(self, ransomNote: str, magazine: str) -> bool: # 统计 magazine 中各字符的数量 char_count = Counter(magazine) # 遍历 ransomNote 中每个字符 for char in ransomNote: if char_count[char] > 0: char_count[char] -= 1 # 消耗一个字符 else: return False # 字符不足,无法构造 return True ``` --- ### 🔍 解释优化后的代码: - `Counter(magazine)`:自动统计每个字符出现的次数,等价于你手动构建的字典。 - `for char in ransomNote`:直接遍历字符,比用索引清晰得多。 - `if char_count[char] > 0`:检查该字符是否还有剩余。 - 注意:`Counter` 访问不存在的键会返回 `0`,不会报错。 - `char_count[char] -= 1`:使用掉一个字符。 - 否则返回 `False`。 这个版本更简洁、安全、易读。 --- ### 🆚 对比说明: | 特性 | 原始代码 | 优化后代码 | |------|---------|-----------| | 时间复杂度 | O(m + n) | O(m + n) | | 空间复杂度 | O(k), k为不同字符数 | O(k) | | 可读性 | 一般 | 很好 | | 命名规范 | 不规范 (`Dict`) | 规范 | | 写法简洁性 | 手动判断是否存在 | 使用 `Counter` 自动处理 | --- ### ✅ 进阶写法(一行解法,适合面试中展示思路多样性) ```python from collections import Counter class Solution: def canConstruct(self, ransomNote: str, magazine: str) -> bool: return not (Counter(ransomNote) - Counter(magazine)) ``` #### 解释: - `Counter(ransomNote) - Counter(magazine)` 表示 `ransomNote` 中哪些字符超出了 `magazine` 的供应。 - 如果结果为空(即布尔值为 `False`),说明可以构造。 - `not (...)` 就返回 `True`。 ⚠️ 注意:这种写法虽然短,但在面试中最好先写清楚逻辑版,再提一句“也可以用 Counter 相减一行解决”。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值