在问 · 算法题解

383. 赎金信

题目描述

输入两个字符串 ransomNote 和 magazine。

判断能否只用 magazine 中的字母拼出 ransomNote。magazine 里每个字母最多只能用一次。

能拼出返回 true,否则返回 false。

示例 1
输入:ransomNote = "a", magazine = "b"
输出:false

解释:magazine 中没有字母 a。

示例 2
输入:ransomNote = "aa", magazine = "ab"
输出:false

解释:需要两个 a,magazine 只有一个。

示例 3
输入:ransomNote = "aa", magazine = "aab"
输出:true

解释:magazine 正好有两个 a。

数据范围

  • 1 <= ransomNote.length, magazine.length <= 10^5
  • 两个字符串都只含小写英文字母

解题思路

用长度为 26 的数组 cnt 记下 magazine 里每个字母有多少个,就是“库存”。再遍历 ransomNote,每用一个字母就把对应库存减 1,一旦减到负数就说明不够用,返回 false;全部用完都没有变负就返回 true。

为什么正确

处理完 ransomNote 的前 i 个字符后,cnt[c] = magazine 中 c 的个数 − 前 i 个字符中 c 的个数。

复杂度分析

时间 O(m + n);空间 O(26)。

易错点

只用 set 判断“字母是否出现”会忽略数量,把 "aa" / "ab" 误判为 true。每次用 str.replace 删字符则是 O(m · n)。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
    def canConstruct(self, ransomNote: str, magazine: str) -> bool:
        cnt = [0] * 26
        for c in magazine:
            cnt[ord(c) - 97] += 1
        for c in ransomNote:
            cnt[ord(c) - 97] -= 1
            if cnt[ord(c) - 97] < 0:
                return False
        return True

载入编辑器,自己跑一遍 →

字符串 专题的其他题目

查看 字符串 全部题目 →