题目链接: https://leetcode.com/problems/ransom-note/
Given two strings ransomNote and magazine, return true if ransomNote can be constructed from magazine and false otherwise.
【Translate】:给定两个字符串ransomNote
和magazine
,如果ransomNote可以从通过magazine中的字符构造出来(换句话说就是,magazine相当于一个字符库,ransomNote则需要从magazine中取字符;其实也就是一个判断单个字符数量的问题),则返回true,否则返回false。
Each letter in magazine can only be used once in ransomNote.
【Translate】:magazine
中的每个字母只能在ransomNote
中使用一次。
测试用例:
约束:
约束要求ransomNote和magazine的长度不小于1,且不大于10五次方;同时还要求字符串内容都是小写字母。
拿到这个题的时候,一开始其实我并没有理解它的意思,只是单纯觉得是判断magazine中是否包含ransomNote。心想要是这样,用python岂不是很简单。于是就有了下面的代码:
class Solution(object):
def canConstruct(self, ransomNote, magazine):
"""
:type ransomNote: str
:type magazine: str
:rtype: bool
"""
if ransomNote in magazine:
return True
else:
return False
上来直接判断一下不就完了,结果提交的时候傻眼了,小丑竟是我自己。这道题虽然是说magazine包含ransomNote,但不是整体包含,而是跟旧日历一样,一次对应一个,用完就撕掉(比喻的可能不太准确,但大概就是这个意思),所以我们真正要判断的是字符串中单个字符的数量。
正确代码如下所示:
class Solution(object):
def canConstruct(self, ransomNote, magazine):
"""
:type ransomNote: str
:type magazine: str
:rtype: bool
"""
for i in set(ransomNote):
if magazine.count(i) < ransomNote.count(i):
return False
return True
Python以其特有的count()函数可以统计出某个字符在该字符串中出现的次数,当然这在便捷的同时也牺牲了时间。
仿照Python实现该题的思想,通过一个数组来记录单字符在magazine中出现的次数,然后遍历ransomNote,减去ransomNote中出现的字符数量,最后就只需要判断一下该位置的数是否小于0即可。
public boolean canConstruct1(String ransomNote, String magazine) {
int[] count = new int[26]; // 定义数组完毕后,自动初始化为0
int i,s = 0;
for(i = 0; i < magazine.length(); i++){
s = magazine.charAt(i) - 'a';
count[s] += 1;
}
for(i = 0; i < ransomNote.length(); i++){
s = ransomNote.charAt(i) - 'a';
count[s] -= 1;
if(count[s] < 0 ){
return false;
}
}
return true;
}
我们可以看到上面虽然得到了较好的时间,但是在空间上还有很大的优化空间。于是,查询到了如下题解,其基本思想都是一样的,但其通过了减少变量,达到了优化空间的目的。
public boolean canConstruct2(String ransomNote, String magazine) {
int[] arr = new int[26];
for (int i = 0; i < magazine.length(); i++) {
arr[magazine.charAt(i) - 'a']++;
}
for (int i = 0; i < ransomNote.length(); i++) {
if(--arr[ransomNote.charAt(i)-'a'] < 0) {
return false;
}
}
return true;
}
关于HashMap这方面,并没有做过多的思考,只是简单的通过HashMap的方式把2.2中数组的思想实现出来了,唯一需要注意的地方就是,在遍历ransomNote的时候需要先判断一下HashMap中是否存在这个键,如果不存在,但是你下面又要对它进行操作,就会报错。
此外还有一个疑问就是,为什么明明HashMap要比数组快,但为什么时间上不如数组要好?这是因为HashMap的快只体现在插入和删除的时候,而在查询的时候因为数组有下标所以在查询集合中某个元素时,一般都会对数组甘拜下风。
public boolean canConstruct(String ransomNote, String magazine) {
if(magazine.length()<ransomNote.length())
return false;
int i,s = 0;
HashMap<Integer,Integer> count= new HashMap<>();
for (i = 0; i < magazine.length(); i++) {
s = magazine.charAt(i) - 'a';
count.put(s, count.getOrDefault(s,0)+1);
}
for (i = 0; i < ransomNote.length(); i++) {
s = ransomNote.charAt(i) - 'a';
if(count.containsKey(s)){
count.replace(s,count.getOrDefault(s,0)-1);
if(count.get(s) < 0){
return false;
}
}else{
return false;
}
}
return true;
}
[1] java数组的初始化
[2] hashmap和数组哪个速度快
[3] python中函数COUNT()的功能是什么
[4] Java 数组
[5] Java HashMap
[6] arr[0]++和++arr[0]之间的差异
[7] java 统计字符串中每个字符出现的次数(数组或HashMap实现)
[8] Java在线测试工具