代码随想录算法训练营第七天 | 454.四数相加II、383. 赎金信、15. 三数之和、18. 四数之和
链接: 454.四数相加II
链接: 383. 赎金信
链接: 15. 三数之和
链接: 18. 四数之和
自己看到题目的第一想法
454.四数相加II :快速查询+返回索引下标我第一时间想到用哈希map,跟昨天的两数之和那道题不一样的点在于,这道题是四个数相加,我在想,两个数相加用一个hashmap存target-nums[i]和i,那么四个数相加岂不是要用两个hashmap?
383. 赎金信:第一想法是为什么这个题的名字要叫赎金信?是否能由对方的字符构成,但是有一个问题是,magazine中的字符串不能重复使用,哈希map可以做出来。把magazine字符串中的单个字符放入map集合或者哈希数组中,遍历ransomNote字符串看看集合中是否都有且不重复。
15.三数之和:将前两个数遍历得到的结果放入map中之后再去查看遍历有无-(a+b)的情况。
18. 四数之和:经过三数之和之后,我看到不去重立马就想到指针法,但是这题并没有规定数都是正数,所以这也是无法排序后缩小范围的一个点。所以我觉得跟三数之和还是不太一样的。
看完代码随想录之后的想法
454.四数相加II :首先hashmap中使用到的api:
//当Map集合中有这个key时,就返回这个key的值;
//如果没有就返回默认值defaultValue。defaultValue类型与Map集合中存储的值的类型一样;
V hashmap.getOrDefault(Object key, V defaultValue);
// 向Map中添加键值对,如果key已存在,则覆盖value
hashmap.put(Object key, V Value)
//返回指定键映射的值,如果不存在键,返回null(引发空指针异常)
V hashmap.get(Object key);
//判断是否含有键,如果有则返回True,如果没有则返回False
boolean hashmap.containsKey(Object key)
总体思路:先遍历A和B两个数组(n的平方),相加作为键,次数作为值,存入map集合中,再遍历C和D,查询-c-d是否出现在map中,并返回次数。
383.赎金信:第一,关于题意:看完解析发现明白为啥叫赎金信了,不能暴露赎金信字迹所以需要在magazine上找到需要的字符。第二,关于方法:此题和有效的字母异位词相似,我的想法是使用hashmap但是题解告诉,使用map的空间消耗要比数组大一些的,因为map要维护红黑树或者哈希表,而且还要做哈希函数,是费时的!数据量大的话就能体现出来差别了。 所以数组更加简单直接有效!
这里贴下这道题和有效的字母异位词相关的代码:
for(char c:magazine.toCharArray()){
cnt[c-'a']++; //转成ASCII码值,索引下标是唯一的,记录字母,值对应字母出现的次数
}
for (int i = 0; i < s.length(); i++) {
record[s.charAt(i) - 'a']++; // 并不需要记住字符a的ASCII,只要求出一个相对数值就可以了
}
15.三数之和:看完题解发现自己有一个地方没有注意,就是不重复的三元组这个条件是指值不重复,而不是索引下标不重复。所以carl提示说使用哈希法会因为这个去重操作而变得繁琐易错,采用排序加指针法更容易实现。但是关于去重有很多细节要注意。去重是个重点逻辑。
18. 四数之和:外面增加了一层for循环,要记住对每一个变量进行去重,并没有规定数一定是大于0的,所以排序后再根据后面的大小来计算。
自己实现过程中遇到哪些困难
454.四数相加II : 记录次数作为值的部分没有看懂。通过群友的解答,举了个例子就懂了。
383. 赎金信:为何使用数组而不使用map的理解。
15.三数之和:去重部分的细节把握。
18.四数之和:去重和剪枝的细节把握。
今日收获,记录一下自己的学习时长
1.两道四数之和题目用到的方法不同,第一道题目的四数之和返回元组数量,并且不需要去重,采用HashMap,第二道四数之和规定返回去重后的元组,采用排序后的指针法。是在三数之和的基础上再加一层循环并去重得到的。同时注意,数是否有规定正负也需要考虑,如果都是正数,且排序后的第一个数大于target就需要剪枝。
2.赎金信这道题,和有效异位词可以一起理解。
3.写完这篇博客我要去把Java集合相关的内容吃透了,拜拜~