题目
难度:★★☆☆☆
类型:字符串
给定一个赎金信 (ransom) 字符串和一个杂志(magazine)字符串,判断第一个字符串ransom能不能由第二个字符串magazines里面的字符构成。如果可以构成,返回 true ;否则返回 false。
(题目说明:为了不暴露赎金信字迹,要从杂志上搜索各个需要的字母,组成单词来表达意思。)
注意:
你可以假设两个字符串均只含有小写字母。
canConstruct("a", "b") -> false
canConstruct("aa", "ab") -> false
canConstruct("aa", "aab") -> true
解答
这道题理解题意很重要,解答非常简单。如果赎金信字符串中出现的所有字符在杂志中均能找到其复制的翻版(一个翻版只能用一次),那么则返回True。这个问题的本质实际上就是数组问题【题目250. 两个数组的交集】的字符串版本,我们可以用同样的办法完成。
方案1:减小字符库
遍历赎金信,每次将遇到的字符与杂志字符库中的字符进行比对,如果杂志字符库中没有这个字符,则杂志支付库中的字符一定不能组成赎金信;如果当前字符在杂志字符库中存在,那么删除杂志字符库中的一个该字符,继续遍历。
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
for note_letter in ransomNote: # 拿出来赎金信中的一个字符
current_magazine = magazine.replace(note_letter, '', 1) # 去掉杂志上的其中一个该字符,参数1为了只删一个
if len(current_magazine) == len(magazine): # 如果没有找到杂志上有这个字符
return False # 赎金信中的这个字符是无法用杂志中的字符组成的
magazine = current_magazine # 更新杂志字符
return True # 赎金信中的所有字符均在杂志中找到了翻版
方案2:字典
本题实际上要求赎金信字符串(字符串1)中各个字符出现的次数不多于要杂志字符库(字符串2)中的相应字符出现的次数,这样杂志字符库中的字符组成赎金信时才够用。这里使用Counter可以直接计算字符的统计字典,通过字典相减判断杂志字符库中的字符是否够用。
from collections import Counter
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
return not (Counter(ransomNote) - Counter(magazine))
如有疑问或建议,欢迎评论区留言~