id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/
公众号:负雪明烛
目录
- 题目描述
- 题目大意
- 解题方法
- 哈希表(字典)
- 数组
- 日期
[LeetCode]
题目地址:https://leetcode.com/problems/ransom-note/
- Difficulty: Easy
题目描述
Given an arbitrary ransom note string and another string containing letters from all the magazines, write a function that will return true if the ransom note can be constructed from the magazines ; otherwise, it will return false.
Each letter in the magazine string can only be used once in your ransom note.
Note:
You may assume that both strings contain only lowercase letters.
canConstruct("a", "b") -> false
canConstruct("aa", "ab") -> false
canConstruct("aa", "aab") -> true
题目大意
判断 ransom 能否由 magazines 的字符构成,也就是说是否是子集。
解题方法
理解题意很关键,这个是说从 magazine 中取出几个元素排列组合能够摆成 ransomNote,所以可以说 ransomNote 是 magazine 的子集。
字符串是否包含/子集的问题,统统用统计词频来做。既然是子集,那么 ransomNote 中每个字符出现的次数都应该小于等于该字符在 magazine 出现的次数。
统计词频有两种方法:哈希表(字典)或者数组。
哈希表(字典)
下面是 Python 解法,可以直接用 Counter 统计词频。
然后判断 ransomNote 的每个字符出现次数都小于等于其在 ransomNote 的出现次数。
Python 代码如下:
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
noteCount = collections.Counter(ransomNote)
magaCount = collections.Counter(magazine)
for note in noteCount:
if magaCount[note] < noteCount[note]:
return False
return True
- 时间复杂度:O(N)
- 空间复杂度:O(N)
数组
因为题目中说了只包含了小写字母,所以可以用有 26 个位置的数组,保存字符出现的次数。
如果使用类似于上面哈希表(字典)的解法,那么需要两个数组。
其实可以用一个数组就够了:
- 先遍历 magazine 的字符,使其在数组中对应位置++;
- 然后再遍历 ransomNote 的字符,使其在数组中对应位置–;
- 如果在发现 – 之后,元素出现的个数小于 0 了,则说明该字符在 magazine 中出现的频率小于在 ransomNote 出现的频率,返回 False。
Java 代码如下:
public class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
if(ransomNote.length() > magazine.length())
return false;
int []chars= new int[26];
for(int i=0; i< magazine.length(); i++){
chars[magazine.charAt(i)- 'a']++;
}
for(int i=0; i< ransomNote.length(); i++){
chars[ransomNote.charAt(i)- 'a']--;
if(chars[ransomNote.charAt(i)- 'a'] < 0){
return false;
}
}
return true;
}
}
- 时间复杂度:O(N)
- 空间复杂度:O(N)
日期
2017 年 1 月 7 日
2018 年 11 月 14 日 —— 很严重的雾霾
2021 年 12 月 4 日 —— 找租房真是一个烦心事