题目
https://leetcode-cn.com/problems/4sum-ii/
解法一
- 先把构成数组插入map中,和之前两数之和一样,key是字母。value是次数。遵循着HashMap的key是不能重复的,如果有相同的key,最后一个key对应的value会把前一个相同的value覆盖掉。
- 循环判断r中元素,m中是否有,若有value-1,若没有即返回false。若value<0也返回false
- String和char区别很大, char是基本数据类型,而String是个类,属于引用数据类型。这里用的是Character类。然后运用String的toCharArray方法将其转换为char型数组。
自动拆装箱
自动装箱: 当我们把一个基本类型的值( 20),赋值给引用变量时候,系统可以 自动将它“包装”为相应的包装类的实例程序需要对象时, 如果给的只是一个基本类型的值, 系统会将它自动装箱为包装类的实例达到的效果: 有了自动装箱之后, 基本类型的值可以当成对象用—— 其实是【假相】 。
自动拆箱: 当我们需要一个基本类型的值时, 但实际上传入的包装类的对象。 系 统会自动把对象“剥”开,得到它的值。 达到的效果: 有了自动拆箱之后, 包装类的对象可当成基本类型的值 用——其实是【假相】 。
public boolean canConstruct(String ransomNote, String magazine){
Map<Character, Integer> map = new HashMap<>();
//key-s;value-次数
for (char s:magazine.toCharArray()) {
if (map.containsKey(s)){
map.put(s,map.get(s)+1);
}else{map.put(s,1);}
}
//循环判断r中元素,m中是否有,若有value-1,若没有即返回false。若value<0也返回false
for (char s:ransomNote.toCharArray()) {
if (map.containsKey(s)){
//注意这两行的顺序
map.put(s,map.get(s)-1);
if (map.get(s)<0){return false;}
}else{return false;}
}
return true;
}
解法二
因为题目所只有小写字母,那可以采用空间换取时间的哈希策略, 用一个长度为26的数组还记录magazine里字母出现的次数。
然后再用ransomNote去验证这个数组是否包含了ransomNote所需要的所有字母。
依然是数组在哈希法中的应用。
一些同学可能想,用数组干啥,都用map完事了,其实在本题的情况下,使用map的空间消耗要比数组大一些的,因为map要维护红黑树或者哈希表,而且还要做哈希函数,是费时的!数据量大的话就能体现出来差别了。 所以数组更加简单直接有效!
根据题意并利用两字符串只包含小写字母,先使用大小为字符集大小的数组(充当哈希表)对 magazinemagazine 进行词频统计,然后在遍历 ransomNoteransomNote 时对计数数组进行抵消操作。
若处理过程中出现词频数量为负数,则说明 magazinemagazine 不能凑出 ransomNoteransomNote。(和解法一操作基本相同)
public static boolean canConstruct(String ransomNote, String magazine) {
int[] arr = new int[26];
//a->0 b->1
for (char c:magazine.toCharArray()) {
arr[c-'a']++;
}
for (char c:ransomNote.toCharArray()) {
arr[c-'a']--;
if (arr[c-'a']<0){return false;}
}
return true;
}
运行确实快了一些