代码随想录算法训练营第七天 | 454.四数相加II ● 383. 赎金信 ● 15. 三数之和 ● 18. 四数之和

今天除了哈希表还有两道双指针的题,383题和昨天做的一道题很像,其他的看了都没什么好的思路。感叹一下暴力解决时间复杂度越来越高了,还是得积累算法的。

454.四数相加II 

题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

这道题用哈希表解决的关键就是Map是如何存储键值对的。把问题优化成两两一组求解,因为这道题只是要求有效解的个数,没要求具体下标,我们只需要用Map来存储nums1和nums2中和的值和这个和出现的个数,用二层嵌套的for循环遍历两个数组,每次如果发现了一个新值就更新Map,否则增加该和出现的次数。

代码如下:

for(int i : nums1){
    for(int j : nums2){
        int sum = i + j;
        sum12.put(sum, sum12.getOrDefault(sum, 0) + 1);
     }
}

对于nums3和nums4,也同样的使用二层for嵌套,寻找HashMap中有没有已经存在的3,4数组中的数的和的相反数。存在几个,对于这个和,就有几个解。

for(int i : nums3){
    for(int j : nums4){
        int sum = i + j;
        if(sum12.containsKey(0 - sum)){
            count += sum12.get(0 - sum);
        }
    }
}

这道题里用到了一个HashMap的轮子函数getOrDefault,它的作用是获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值。这样的话,就可以很容易的更新key所对应的sum出现的次数,

383. 赎金信 

题目链接:https://leetcode.cn/problems/ransom-note/description/

这道题和昨天的242题很像,我的做法也基本一样,用数组来充当哈希表,先遍历magazine来获取每个字母出现几次,然后遍历randomNote,出现一个字符就减去一次,如果某个字符出现次数小于0了,就证明不符合题意,直接返回了。

15. 三数之和 

题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

18. 四数之和 

题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

这两道题基本上是一样的,就是四数之和要多一重for循环,别的基本就是照搬,就放在一起说。

可以看出这两个题如果直接暴力的话,时间复杂度很高,采取双指针的方式来做的话就可以降低一个指数级别。

【其实感觉也有点像滑动窗口】

具体就是先排序,这样的话就会有一定的规律可循。三数之和用for循环固定第一个数字,四数之和用二重for循环固定前两个数字,然后用双指针划定left和right,如果几个数的和小了,那么就需要右移left指针,从而使nums[left]变大(记住数组已经是有序的了),同样如果几个数的和大了,就左移right指针。当移动到left比right大了,就证明这一组已经遍历完了,没有符合要求的,可以进行下一组。

上面说的是基本思想。实际操作的时候要注意,几个数的和可能会超过int限制,要进行一下强制转换换成long类型。

然后要注意一点就是要去重,不是指题目里的下标不能相等,而是对于返回的那个二维数组,里面不能有重复的元素。比如说,nums[]里面可能有一些相同的元素,这就可能导致满足结果的几个数值相同,不满足条件。其实这是集合的一种性质,感觉可以用Set接口来进行处理。不过也有单独的判断方式,就是每次左移和右移后,判断一下新指的和旧指的是否相同,如果相同的话,就要跳过这个新指的,因为不跳过的话必然会导致答案重复。

在满足了以上的条件之后其实就可以过了,但还应该进行一些必要的剪枝。比如如果这一组数最小的都比target要大,鉴于我们是从左往右处理,和就必然比target大了,后面的数肯定只会更大,那么这个时候就可以返回了。

语法方面:

1. 二维数组ArrayList怎么创建:List<List<Integer>> result = new ArrayList<List<Integer>>();

2. 上面提到的需要强制转换,涉及加和乘操作的时候需要多注意;

3. 把几个数加到二维数组里,用到Arrays里面的函数:result.add(Arrays.asList(nums[i], nums[left], nums[right]));

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值