LeetCode 383 赎金信


文章目录

    • 摘要
    • 描述
    • 题解答案
    • 题解代码分析
      • 1. 字符计数的方法
      • 2. 统计 magazine 中的字符
      • 3. 检查 ransomNote 中的字符
      • 4. 为什么这样能解决问题?
      • 5. 优化:提前返回
    • 示例测试及结果
      • 示例 1:ransomNote = "a", magazine = "b"
      • 示例 2:ransomNote = "aa", magazine = "ab"
      • 示例 3:ransomNote = "aa", magazine = "aab"
      • 示例 4:ransomNote = "abc", magazine = "aabbcc"
      • 示例 5:ransomNote = "aabb", magazine = "ab"
    • 时间复杂度
    • 空间复杂度
    • 实际应用场景
      • 场景一:文本分析
      • 场景二:拼写检查
      • 场景三:资源分配
      • 场景四:字符频率分析
      • 场景五:字谜游戏
    • 总结

摘要

这道题其实挺有意思的,它模拟了一个经典的场景:用杂志上的字母拼出勒索信。题目要求我们判断ransomNote能不能由magazine里面的字符构成,而且magazine中的每个字符只能用一次。

听起来像是一个字符串匹配问题,但实际上是一个字符计数问题。我们需要统计magazine中每个字符的出现次数,然后检查ransomNote中的每个字符是否都有足够的数量。今天我们就用 Swift 来搞定这道题,顺便聊聊这种字符计数的方法在实际开发中的应用场景。

描述

题目要求是这样的:给你两个字符串ransomNotemagazine,判断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 <= 10^5
  • ransomNotemagazine由小写英文字母组成

这道题的核心思路是什么呢?我们需要统计magazine中每个字符的出现次数,然后遍历ransomNote,每遇到一个字符,就从统计中减去一次。如果某个字符的计数变成负数,说明magazine中没有足够的字符来构成ransomNote,返回false。如果遍历完ransomNote都没有出现负数,说明可以构成,返回true

题解答案

下面是完整的 Swift 解决方案:

classSolution{funccanConstruct(_ransomNote:String,_magazine:String)->Bool{// 统计 magazine 中每个字符的出现次数varcharCount:[Character:Int]=[:]forcharinmagazine{charCount[char,default:0]+=1}// 遍历 ransomNote,检查每个字符是否都有足够的数量forcharinransomNote{// 如果字符不存在或数量不足,返回 falseifletcount=charCount[char],count>0{charCount[char]=count-1}else{returnfalse}}returntrue}}

题解代码分析

让我们一步步分析这个解决方案:

1. 字符计数的方法

这道题的核心是统计字符的出现次数。我们可以用一个字典来存储每个字符及其出现次数:

varcharCount:[Character:Int]=[:]

字典的键是字符,值是该字符在magazine中出现的次数。

2. 统计 magazine 中的字符

首先,我们需要统计magazine中每个字符的出现次数:

forcharinmagazine{charCount[char,default:0]+=1}

这里使用了 Swift 字典的default参数,如果字符不存在,默认值为 0,然后加 1。如果字符已存在,就直接加 1。

示例:

假设magazine = "aab"

  • 遍历到 ‘a’:charCount['a'] = 1
  • 遍历到 ‘a’:charCount['a'] = 2
  • 遍历到 ‘b’:charCount['b'] = 1

最终charCount = ['a': 2, 'b': 1]

3. 检查 ransomNote 中的字符

接下来,我们需要检查ransomNote中的每个字符是否都有足够的数量:

forcharinransomNote{ifletcount=charCount[char],count>0{charCount[char]=count-1}else{returnfalse}}

对于ransomNote中的每个字符:

  1. 检查该字符是否在字典中存在,且数量大于 0
  2. 如果存在且数量足够,将该字符的计数减 1
  3. 如果不存在或数量不足,返回false

示例:

假设ransomNote = "aa"magazine = "aab"

  • 第一次遍历到 ‘a’:charCount['a'] = 2 > 0,减 1,charCount['a'] = 1
  • 第二次遍历到 ‘a’:charCount['a'] = 1 > 0,减 1,charCount['a'] = 0
  • 遍历完成,返回true

如果ransomNote = "aa"magazine = "ab"

  • 第一次遍历到 ‘a’:charCount['a'] = 1 > 0,减 1,charCount['a'] = 0
  • 第二次遍历到 ‘a’:charCount['a'] = 0,不满足count > 0,返回false

4. 为什么这样能解决问题?

这个算法的核心思想是:

  • 用字典统计magazine中每个字符的可用数量
  • 遍历ransomNote时,每使用一个字符,就从可用数量中减去 1
  • 如果某个字符的可用数量变成 0 或负数,说明不够用了,返回false
  • 如果所有字符都够用,返回true

5. 优化:提前返回

如果ransomNote的长度大于magazine的长度,肯定无法构成,可以提前返回:

classSolution{funccanConstruct(_ransomNote:String,_magazine:String)->Bool{// 优化:如果 ransomNote 比 magazine 长,肯定无法构成ifransomNote.count>magazine.count{returnfalse}varcharCount:[Character:Int]=[:]forcharinmagazine{charCount[char,default:0]+=1}forcharinransomNote{ifletcount=charCount[char],count>0{charCount[char]=count-1}else{returnfalse}}returntrue}}

这个优化可以避免不必要的计算,提高效率。

示例测试及结果

让我们用几个例子来测试一下这个解决方案:

示例 1:ransomNote = “a”, magazine = “b”

letsolution=Solution()letresult1=solution.canConstruct("a","b")print("示例 1 结果:\(result1)")// 输出: false

执行过程分析:

  1. 统计magazinecharCount = ['b': 1]
  2. 遍历ransomNote
    • 字符 ‘a’:charCount['a']不存在,返回false

结果:false,因为magazine中没有字符 ‘a’。

示例 2:ransomNote = “aa”, magazine = “ab”

letresult2=solution.canConstruct("aa","ab")print("示例 2 结果:\(result2)")// 输出: false

执行过程分析:

  1. 统计magazinecharCount = ['a': 1, 'b': 1]
  2. 遍历ransomNote
    • 第一次字符 ‘a’:charCount['a'] = 1 > 0,减 1,charCount['a'] = 0
    • 第二次字符 ‘a’:charCount['a'] = 0,不满足count > 0,返回false

结果:false,因为magazine中只有 1 个 ‘a’,但ransomNote需要 2 个 ‘a’。

示例 3:ransomNote = “aa”, magazine = “aab”

letresult3=solution.canConstruct("aa","aab")print("示例 3 结果:\(result3)")// 输出: true

执行过程分析:

  1. 统计magazinecharCount = ['a': 2, 'b': 1]
  2. 遍历ransomNote
    • 第一次字符 ‘a’:charCount['a'] = 2 > 0,减 1,charCount['a'] = 1
    • 第二次字符 ‘a’:charCount['a'] = 1 > 0,减 1,charCount['a'] = 0
  3. 遍历完成,返回true

结果:true,因为magazine中有 2 个 ‘a’,足够构成ransomNote

示例 4:ransomNote = “abc”, magazine = “aabbcc”

letresult4=solution.canConstruct("abc","aabbcc")print("示例 4 结果:\(result4)")// 输出: true

执行过程分析:

  1. 统计magazinecharCount = ['a': 2, 'b': 2, 'c': 2]
  2. 遍历ransomNote
    • 字符 ‘a’:charCount['a'] = 2 > 0,减 1,charCount['a'] = 1
    • 字符 ‘b’:charCount['b'] = 2 > 0,减 1,charCount['b'] = 1
    • 字符 ‘c’:charCount['c'] = 2 > 0,减 1,charCount['c'] = 1
  3. 遍历完成,返回true

结果:true,所有字符都有足够的数量。

示例 5:ransomNote = “aabb”, magazine = “ab”

letresult5=solution.canConstruct("aabb","ab")print("示例 5 结果:\(result5)")// 输出: false

执行过程分析:

  1. 优化检查:ransomNote.count = 4 > magazine.count = 2,提前返回false

结果:false,因为ransomNotemagazine长,肯定无法构成。

时间复杂度

让我们分析一下这个算法的时间复杂度:

时间复杂度:O(m + n)

其中:

  • mmagazine的长度
  • nransomNote的长度

分析:

  1. 统计magazine中的字符:需要遍历magazine一次,时间复杂度 O(m)
  2. 检查ransomNote中的字符:需要遍历ransomNote一次,时间复杂度 O(n)
  3. 字典操作:字典的查找、插入、更新操作平均时间复杂度都是 O(1)

所以总时间复杂度是 O(m + n)。

对于题目约束(ransomNote.length, magazine.length <= 10^5),这个时间复杂度是完全可接受的。

空间复杂度

让我们分析一下这个算法的空间复杂度:

空间复杂度:O(k)

其中kmagazine中不同字符的个数。

分析:

我们使用了一个字典来存储每个字符的出现次数。字典的大小取决于magazine中不同字符的个数。

由于题目提示ransomNotemagazine由小写英文字母组成,所以最多只有 26 个不同的字符。因此,空间复杂度实际上是 O(26) = O(1)。

但在一般情况下,如果字符集更大,空间复杂度就是 O(k),其中 k 是不同字符的个数。

实际应用场景

这种字符计数的方法在实际开发中应用非常广泛:

场景一:文本分析

在文本分析中,我们经常需要统计字符或单词的出现次数:

funcanalyzeText(_text:String)->[Character:Int]{varcharCount:[Character:Int]=[:]forcharintext{charCount[char,default:0]+=1}returncharCount}

场景二:拼写检查

在拼写检查中,我们需要检查一个单词能否由给定的字母组成:

funccanSpell(_word:String,with letters:String)->Bool{varletterCount:[Character:Int]=[:]forletterinletters{letterCount[letter,default:0]+=1}forcharinword{ifletcount=letterCount[char],count>0{letterCount[char]=count-1}else{returnfalse}}returntrue}

场景三:资源分配

在资源分配中,我们需要检查是否有足够的资源来完成某个任务:

funccanAllocate(_requirements:[String:Int],_available:[String:Int])->Bool{for(resource,needed)inrequirements{ifletavailableCount=available[resource],availableCount>=needed{continue}else{returnfalse}}returntrue}

场景四:字符频率分析

在密码学或数据分析中,我们需要分析字符的频率:

funccharacterFrequency(_text:String)->[(Character,Int)]{varfrequency:[Character:Int]=[:]forcharintext{frequency[char,default:0]+=1}returnfrequency.sorted{$0.value>$1.value}}

场景五:字谜游戏

在字谜游戏中,我们需要检查一个单词能否由给定的字母组成:

funccanFormWord(_word:String,from letters:String)->Bool{ifword.count>letters.count{returnfalse}varletterCount:[Character:Int]=[:]forletterinletters{letterCount[letter,default:0]+=1}forcharinword{ifletcount=letterCount[char],count>0{letterCount[char]=count-1}else{returnfalse}}returntrue}

总结

这道题虽然看起来简单,但实际上涉及了一个很重要的算法思想:字符计数。通过统计字符的出现次数,我们可以高效地解决很多字符串相关的问题。

关键点总结:

  1. 字符计数:使用字典统计每个字符的出现次数
  2. 逐个检查:遍历目标字符串,检查每个字符是否都有足够的数量
  3. 及时返回:如果某个字符不够,立即返回false
  4. 优化技巧:如果目标字符串比源字符串长,可以提前返回

算法优势:

  1. 时间复杂度低:只需要遍历两个字符串各一次,O(m + n)
  2. 空间复杂度低:只需要一个字典,O(k),对于小写字母来说就是 O(1)
  3. 实现简单:代码逻辑清晰,容易理解和维护

实际应用:

字符计数的方法在很多场景中都有应用,比如文本分析、拼写检查、资源分配、字符频率分析、字谜游戏等。掌握这种方法,可以帮助我们解决很多类似的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1211519.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java 实战 - 字符编码问题解决方案

网罗开发&#xff08;小红书、快手、视频号同名&#xff09;大家好&#xff0c;我是 展菲&#xff0c;目前在上市企业从事人工智能项目研发管理工作&#xff0c;平时热衷于分享各种编程领域的软硬技能知识以及前沿技术&#xff0c;包括iOS、前端、Harmony OS、Java、Python等方…

LLMs之ISC:《Enhancing LLM Planning Capabilities through Intrinsic Self-Critique》翻译与解读

LLMs之ISC&#xff1a;《Enhancing LLM Planning Capabilities through Intrinsic Self-Critique》翻译与解读 导读&#xff1a;本文提出并验证了一种结构化的“内在自我批评”迭代方法—内在自检推动LLM规划能力跃升—通过让模型逐步生成计划、逐条检验动作前置条件并把历史失…

干货大集合!AI应用架构师构建AI系统性能监控平台全攻略

干货大集合&#xff01;AI应用架构师构建AI系统性能监控平台全攻略 关键词 AI系统性能监控、可观测性三支柱、Metrics设计、分布式追踪、模型漂移检测、Prometheus&Grafana、根因分析 摘要 当你花费数月搭建的AI推荐系统突然因为推理延迟飙升导致用户流失&#xff0c;或…

AI原生应用领域边缘推理:实现实时智能决策的关键

AI原生应用领域边缘推理&#xff1a;实现实时智能决策的关键关键词&#xff1a;AI原生应用、边缘推理、实时智能决策、边缘计算、云计算摘要&#xff1a;本文深入探讨了AI原生应用领域中边缘推理这一实现实时智能决策的关键技术。首先介绍了相关背景&#xff0c;包括目的、预期…

2025网文新手必看避坑指南:新人逆袭SOP|投稿指南+AI写小说工具合集

我是你们的老朋友。在圈子里摸爬滚打了这么久&#xff0c;太懂那种感觉了——想写小说赚点零花钱&#xff0c;脑洞有了&#xff0c;打开文档却憋不出半个字&#xff1b;或者辛辛苦苦写了三万字&#xff0c;投给编辑&#xff0c;结果连个水花都没有。 说实话&#xff0c;现在的网…

盘点10个顶级写小说软件!ai写小说效率提升10倍,一个人顶一个编辑部!

也想在知乎、番茄或是晋江一书封神&#xff1f;作为一名在知乎摸爬滚打多年、坐拥百万粉丝的自媒体博主&#xff0c;我太了解写小说的那种痛苦了。&#x1f4da; 每天坐在电脑前&#xff0c;对着空白文档发呆&#xff0c;明明脑子里有个惊天动地的故事&#xff0c;一落笔却是“…

有哪些免费好用的AI写小说软件?盘点2026年AI写作10大辅助工具

一、AI辅助创作已成网文圈“隐形刚需” 现在的网文圈有一个心照不宣的秘密&#xff1a;虽然大家嘴上都在骂AI&#xff0c;但私底下偷偷用写小说软件辅助的人越来越多了。 据行业内部观察&#xff0c;2025年起&#xff0c;完全拒绝AI辅助的“纯手工”作者正在面临巨大的产能焦虑…

2026新手指南:盘点5款好用的写小说软件,第一款简直是“日更救星”!

很多刚入行的朋友常问我&#xff1a;“为什么我有那么多惊天动地的脑洞&#xff0c;可一打开文档就大脑一片空白&#xff1f;” 其实&#xff0c;99%的新人作者不是没天赋&#xff0c;而是顾虑太多。脑子里的设定堪比史诗巨作&#xff0c;手底下的字数却尴尬地停在第一行。这就…

从零开始写网文:2026年最强小说软件生成器深度横评与避坑指南

很多新人作者问我&#xff1a;“大神&#xff0c;为什么我设定做得比《三体》还宏大&#xff0c;可一动笔就觉得干巴巴的&#xff1f;” 其实问题很简单&#xff1a;你的脑子在天上飞&#xff0c;手却在地上爬。对于新手来说&#xff0c;最痛苦的不是没有创意&#xff0c;而是…

探索未来智能记忆系统 - MemU

MemU: 前沿智能记忆系统 在当今人工智能和大语言模型&#xff08;LLMs&#xff09;快速发展的背景下&#xff0c;MemU应运而生。它是一个功能强大的智能记忆框架&#xff0c;旨在为LLM和AI智能体提供后端支持&#xff0c;能够处理多模态输入&#xff08;包括对话、文档、图像等…

[特殊字符] 提升你编码效率的超级助手:Awesome GitHub Copilot

&#x1f916; 让你的GitHub Copilot焕然一新 — Awesome GitHub Copilot Customizations 在开发过程中&#xff0c;GitHub Copilot凭借其出色的辅助编码功能&#xff0c;已经成为了许多开发者的得力助手。今天&#xff0c;我们将介绍一个为GitHub Copilot提供强大定制功能的项…

【心电信号ECG】QRS波和峰值的检测(从噪声和清晰信号中获得心跳)附Matlab代码和报告

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。 &#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室 &#x1f447; 关注我领取海量matlab电子书和数学建模资料 &#…

2026年市面上评价好的一体板加工厂怎么选,仿石漆保温装饰一体板/保温装饰一体板,一体板厂家哪家权威

外墙装饰一体板作为建筑节能领域的核心材料,直接影响建筑外立面的美观性、耐久性及节能效率。随着绿色建筑标准升级,市场对高品质一体板的需求持续攀升,如何从众多厂家中筛选出技术领先、服务完善、性价比突出的合作…

攻防世界ics-06

1.观察题目拿到题目随便乱点看看有没有什么地方可以跳转的发现报表中心可以跳转看看能不能找到跳转点用sqlmap发现不行 用bp试试看发现在get请求中的id 2.使用bp进行爆破选中这段送入intruder中添加payload先小范围尝试…

微软开源 VibeVoice:90 分钟播客级语音合成技术解析

一个改变语音合成的技术突破 你有没有想过,输入一段对话脚本,AI 就能生成两个人自然交谈 90 分钟的播客音频——不是机械的电子音,而是有停顿、有情感、能互动的真实对话。 微软刚开源的 VibeVoice 做到了。它解决了…

高德地图 API Key 获取指南

概述 高德地图开放平台为开发者提供丰富的地图服务 API&#xff0c;包括地图展示、定位、搜索、路线规划等功能。获取 API Key 是使用高德地图服务的第一步。一、准备工作 1. 注册账号访问官网&#xff1a;https://lbs.amap.com/注册开发者账号&#xff1a; 点击右上角"注…

best work

on the boundary of laws. people dont want to touch them, will be poorer, called left; but on the boundary, its capitalism.

在 Coze(扣子)中搭建自定义智能体

概述 Coze&#xff08;扣子&#xff09;是字节跳动推出的 AI 应用开发平台&#xff0c;支持通过自然语言和可视化配置创建自定义智能体。本文档以天气服务智能体为例&#xff0c;详细介绍如何在 Coze 平台搭建一个完整的自定义智能体。 一、准备工作 1.1 注册账号 访问 Coze…

一维振动信号变为二维灰度图,利用局部二值模式(LBP)深化灰度图特征,然后利用CNN进行特征提取,最后使用softmax分类器和SVM进行分类对比(Python代码,解压缩后直接运行)

运行效果&#xff1a;一维振动信号变为二维灰度图&#xff0c;利用局部二值模式(LBP)深化灰度图特征&#xff0c;然后利用CNN进行特征提取&#xff0c;最后使用softmax分类器和SVM进行分类对比&#xff08;Python_哔哩哔哩_bilibili 所有用到的库的版本 1.数据集&#xff08;凯…

机械寿命预测(基于NASA C-MAPSS数据的剩余使用寿命RUL预测,Python代码,CNN_LSTM模型,有详细中文注释)

1.效果视频&#xff1a;机械寿命预测&#xff08;NASA涡轮风扇发动机剩余使用寿命RUL预测&#xff0c;Python代码&#xff0c;CNN_LSTM模型&#xff0c;有详细中文注释&#xff09;_哔哩哔哩_bilibili 环境库版本&#xff1a; 2.数据来源&#xff1a;https://www.nasa.gov/int…