leetcode389:赎金信
给你两个字符串:ransomNote
和 magazine
,判断 ransomNote
能不能由 magazine
里面的字符构成。
如果可以,返回 true
;否则返回 false
。
magazine
中的每个字符只能在 ransomNote
中使用一次。
示例 1:
输入:ransomNote = "a", magazine = "b" 输出:false
示例 2:
输入:ransomNote = "aa", magazine = "ab" 输出:false
示例 3:
输入:ransomNote = "aa", magazine = "aab" 输出:true
提示:
1 <= ransomNote.length, magazine.length <= 105
ransomNote
和magazine
由小写英文字母组成
步骤1:计算问题分析
问题性质: 我们需要判断字符串 ransomNote
能否完全由字符串 magazine
中的字符组成。每个字符在 magazine
中只能被使用一次,因此该问题本质上是一个 字符频次匹配问题。
输入:
- 一个字符串
ransomNote
,表示我们需要组成的内容。 - 一个字符串
magazine
,表示我们可以从中取字符的来源。
输出:
- 如果
ransomNote
中的所有字符都能在magazine
中找到,并且magazine
中每个字符的出现次数足够匹配ransomNote
,则返回true
;否则返回false
。
限制条件:
- 字符串长度在 1 到 100,000 之间,要求算法必须高效。
- 两个字符串仅由小写英文字母组成,意味着字符范围是固定的(26个字母),这为我们提供了一个优化方向。
潜在边界条件:
ransomNote
的长度大于magazine
,直接返回false
。ransomNote
和magazine
都只有一个字符,简单直接对比。ransomNote
包含某个字符的次数多于magazine
中该字符的次数。
步骤2:解题思路和算法设计
问题分解:
- 字符统计:我们需要统计
ransomNote
和magazine
中每个字符出现的次数。 - 字符匹配:逐一检查
ransomNote
中每个字符是否都能在magazine
中找到足够的数量。
最佳算法设计思路: 我们可以采用计数法解决这个问题,这是一个直接的贪心算法。我们可以将这两个字符串中的字符逐个统计,确保 magazine
中的每个字符出现的次数足够多以满足 ransomNote
中对应字符的需求。
步骤如下:
- 用一个长度为 26 的数组
magazineCount
统计magazine
中各字符的出现次数。 - 然后遍历
ransomNote
,对于每个字符,检查magazineCount
中对应字符的数量是否足够。如果在任何时候magazineCount
中某个字符的数量小于ransomNote
所需数量,直接返回false
。 - 如果遍历结束,说明所有字符的需求都能满足,返回
true
。
时间复杂度:
- 统计
magazine
的字符频次需要 O(n) 的时间,n 是magazine
的长度。 - 统计
ransomNote
的字符频次并进行匹配需要 O(m) 的时间,m 是ransomNote
的长度。 - 整体时间复杂度为 O(m + n),这是线性的,适合处理 100,000 个字符的规模。
空间复杂度:
- 我们只需要一个长度为 26 的数组来统计字符频次,因此空间复杂度为 O(1)。
步骤3:C++代码实现
代码详解:
magazineCount
是一个长度为 26 的数组,分别表示每个小写字母的出现次数。c - 'a'
计算出字符c
对应数组下标(0 对应 'a',25 对应 'z')。- 第一个
for
循环用来统计magazine
中每个字符的频次。 - 第二个
for
循环遍历ransomNote
,如果magazineCount
中某个字符的数量为 0,则说明该字符的数量不足,直接返回false
。如果字符数量足够,则减少对应字符的数量。 - 如果所有字符需求都能满足,则返回
true
。
步骤4:启发与算法优化
通过这道题目,我们可以学到:
- 贪心算法的应用:此题使用了贪心算法,通过一次遍历解决问题,不需要反复检查。
- 空间与时间优化的平衡:利用一个固定大小的数组存储字符频次,这种方法既节省了空间,也让查找字符频次变得非常高效。
- 大规模数据集的处理:由于问题规模较大,选择线性时间复杂度的算法是最优的选择,确保能够在合理的时间内完成计算。
步骤5:实际应用场景
该算法在实际生活中有广泛的应用,特别是在以下场景中:
- 文档验证与构建:在需要从一个大型文本库中提取特定内容时,确保文本库中包含所需字符并且没有重复使用字符的情况。这在文档生成、印刷以及排版系统中是一个常见的需求。
- 字符串匹配与资源分配:该算法也可以应用于资源分配问题,例如工厂的物料匹配。如果工厂有一批材料要生产多个订单,可以用类似的算法确定是否可以用现有材料满足所有订单需求。
实际应用示例: 在一个印刷厂中,需要根据客户的需求打印特定的字母组合。每批墨盒只包含有限数量的字母打印墨水,算法可以用来检查墨盒是否可以支持打印任务,从而优化墨水的使用和订单的管理。