当前位置: 首页 > article >正文

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个字母),这为我们提供了一个优化方向。

潜在边界条件

  1. ransomNote 的长度大于 magazine,直接返回 false
  2. ransomNotemagazine 都只有一个字符,简单直接对比。
  3. ransomNote 包含某个字符的次数多于 magazine 中该字符的次数。

步骤2:解题思路和算法设计

问题分解

  1. 字符统计:我们需要统计 ransomNotemagazine 中每个字符出现的次数。
  2. 字符匹配:逐一检查 ransomNote 中每个字符是否都能在 magazine 中找到足够的数量。

最佳算法设计思路: 我们可以采用计数法解决这个问题,这是一个直接的贪心算法。我们可以将这两个字符串中的字符逐个统计,确保 magazine 中的每个字符出现的次数足够多以满足 ransomNote 中对应字符的需求。

步骤如下:

  1. 用一个长度为 26 的数组 magazineCount 统计 magazine 中各字符的出现次数。
  2. 然后遍历 ransomNote,对于每个字符,检查 magazineCount 中对应字符的数量是否足够。如果在任何时候 magazineCount 中某个字符的数量小于 ransomNote 所需数量,直接返回 false
  3. 如果遍历结束,说明所有字符的需求都能满足,返回 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:启发与算法优化

通过这道题目,我们可以学到:

  1. 贪心算法的应用:此题使用了贪心算法,通过一次遍历解决问题,不需要反复检查。
  2. 空间与时间优化的平衡:利用一个固定大小的数组存储字符频次,这种方法既节省了空间,也让查找字符频次变得非常高效。
  3. 大规模数据集的处理:由于问题规模较大,选择线性时间复杂度的算法是最优的选择,确保能够在合理的时间内完成计算。

步骤5:实际应用场景

该算法在实际生活中有广泛的应用,特别是在以下场景中:

  • 文档验证与构建:在需要从一个大型文本库中提取特定内容时,确保文本库中包含所需字符并且没有重复使用字符的情况。这在文档生成、印刷以及排版系统中是一个常见的需求。
  • 字符串匹配与资源分配:该算法也可以应用于资源分配问题,例如工厂的物料匹配。如果工厂有一批材料要生产多个订单,可以用类似的算法确定是否可以用现有材料满足所有订单需求。

实际应用示例: 在一个印刷厂中,需要根据客户的需求打印特定的字母组合。每批墨盒只包含有限数量的字母打印墨水,算法可以用来检查墨盒是否可以支持打印任务,从而优化墨水的使用和订单的管理。


http://www.kler.cn/news/357995.html

相关文章:

  • 效果不错的论文介绍:Im2Flow2Act:-跨领域机器人操控技术
  • 101 - Lecture 9
  • Python 多线程学习与使用
  • 《计算机视觉》—— 基于 dlib 库的方法将两张人脸图片进行换脸
  • React Agent 自定义实现
  • 记录 Latex 中 align 环境下, 两个对齐
  • 在Ubuntu上安装Docker以及使用
  • Linux服务器前后端项目部署vue+springboot—搭建服务器上的运行环境(JDK、Redis、MySQL、Nginx)
  • 十四、行为型(观察者模式)
  • Netty无锁化设计之对象池实现
  • C语言(函数)—函数栈帧的创建和销毁
  • 机器学习与神经网络:诺贝尔物理学奖的新纪元
  • tensorRT_Pro自学记录
  • Java_EE 网络编程(TCP与UDP通信)
  • 类与对象(三)
  • 2024-10-16 学习人工智能的Day8
  • 【设计模式】深入理解Python中的适配器模式(Adapter Pattern)
  • Spring Boot中使用FlexyPool动态监控管理数据库连接池
  • 自己用react开发了一张Es6的学习页面(持续更新系列)
  • 【计算机网络 - 基础问题】每日 3 题(四十七)