DAY7|四数相加II,赎金信,三数之和,四数之和

本文介绍了四数相加II问题的解法,利用哈希映射存储两数组元素和及其出现次数,以及三数之和问题的衍生处理,包括如何考虑目标值和负数情况下的枝剪策略。通过实例代码展示了如何用Java实现这两个问题的解决方案。
摘要由CSDN通过智能技术生成

454.四数相加II

文档讲解四数相加II

视频链接代码随想录-四数相加II

状态:ok

思路:

该题和昨天的两数之和感觉比较类似;此题是每两个数组进行操作;

1、先定义一个map集合,key存储nums1[i]和nums2[j]的和,value存储nums1[i]+nums2[j]对应出现的次数;

2、然后遍历nums3和nums4两个数组,判断key = 0-(nums3[i]+nums4[j])是否存在于map中,如果存在,则计数count+map.get(key);

代码:

class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        HashMap<Integer, Integer> map12 = new HashMap<>();
        for (int i = 0; i < nums1.length; i++) {
            for (int j = 0; j < nums2.length; j++) {
                int sumAB = nums1[i] + nums2[j];
                if (!map12.containsKey(sumAB)) {
                    map12.put(sumAB, 1);
                } else {
                    Integer num = map12.get(sumAB);
                    map12.put(sumAB, ++num);
                }
            }
        }
        int count = 0;
        for (int i : nums3) {
            for (int j : nums4) {
                int sumAB = 0 - i - j;
                if (map12.containsKey(sumAB)) {
                    count += map12.get(sumAB);
                }
            }
        }
        return count;
    }java
}

383.赎金信

文档讲解赎金信

状态:此题类似于昨天写的有效的字母异位词那一题,昨天刷过哪一题之后,这题写出来了;

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        HashMap<Integer, Integer> magaMap = new HashMap<>();
        for (int i = 0; i < magazine.length(); i++) {
            int charNum = magazine.charAt(i) - 'a';
            if (magaMap.containsKey(charNum)) {
                magaMap.put(charNum, (magaMap.get(charNum) + 1));
            } else {
                magaMap.put(charNum, 1);
            }
        }
        for (int i = 0; i < ransomNote.length(); i++) {
            int charNum = ransomNote.charAt(i) - 'a';
            if (!magaMap.containsKey(charNum) || magaMap.get(charNum) <= 0) {
                return false;
            }
            magaMap.put(charNum, (magaMap.get(charNum)-1));
        }
        return true;
    }
}

15.三数之和

文档讲解三数之和

视频链接代码随想录-三数之和

状态:看完讲解后实现了,这题有难度

思路:

1、先对数组进行排序(因为题目没有要求返回对应的数组下标,所以可以打乱原先的数据顺序);

2、排序之后,先用i进行数组遍历,然后定义left=i+1,right=nums.length-1;方便进行三元组查找,left和right定义在两侧,是为了进行数据查找,当num[i]+num[left]+num[right]>0时,将right往里缩(即right–),反之,left往里缩(即left++);
在这里插入图片描述

3、对遍历进行去重和收集操作,这一步非常关键;去重操作例如:“nums[i] == nums[i - 1]”,为什么是与前一个元素比较,而不是"nums[i] == nums[i + 1]“与下一个元素比较呢?问题在于,如果你与下一个元素比较后直接continue,那么就相当于不收集这个元素了,自己体会;再例如:当nums[i] + nums[left] + nums[right] = 0时,收集完三元组后,对num[left]和num[right]去重,即操作"nums[right] == nums[right - 1]”,“nums[left] == nums[left + 1]”;

代码:

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        //非常关键的一步,先将数组排序
        Arrays.sort(nums);
        //使用双指针完成三数之和
        for (int i = 0; i < nums.length; i++) {
            //如果nums[i]大于0了,则后边的再num[left]+num[right]就没有意义了
            if (nums[i] > 0) {
                return result;
            }
            //去重操作,对i即对三元组第一个元素进行去重
            if (i > 0 && nums[i] == nums[i - 1]) {
                continue;
            }
            //定义双指针遍历查找是否存在 nums[i] + nums[left] + nums[right] = 0
            int left = i + 1;
            int right = nums.length - 1;
            while (left < right) {
                int sum = nums[i] + nums[left] + nums[right];
                if (sum > 0) { //说明数据大了,需要right指针往里缩
                    right--;
                } else if (sum < 0) { //说明数据小了,left指针要往上加
                    left++;
                } else { //此时等于0了,可以开始收集结果集了,但是这里又要考虑去重的问题,非常关键
                    result.add(Arrays.asList(nums[i], nums[left], nums[right]));
                    while (left < right && nums[right] == nums[right - 1])
                        right--;
                    while (left < right && nums[left] == nums[left + 1])
                        left++;
                    right--;
                    left++;
                }
            }
        }
        return result;
    }
}

18.四数之和*

文档讲解四数之和

视频链接代码随想录-四数之和

状态:禁止套娃🪆

思路:

1、这题可以看成是三数之和的衍生题,但是此题需要注意的是,三数之和要求target=0,而此题target可能是任意数,所以,在对循环进行枝剪时,要注意考虑target和nums[k]和为负数的情况;

代码:

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> result = new ArrayList<>();
        //排序
        Arrays.sort(nums);
        //此题注意有负数的情况,因为三数之和时要求和为0,所以第一层可以做枝剪
        for (int k = 0; k < nums.length; k++) {
            //第一层枝剪
            if (nums[k] > 0 && nums[k] > target) {
                return result;
            }
            //k位置第一个元素去重
            if (k > 0 && nums[k] == nums[k-1]) {
                continue;
            }
            for (int i = k+1; i < nums.length; i++) {
                if (i > k+1 && nums[i] == nums[i-1]) {
                    continue;
                }
                int left = i + 1;
                int right = nums.length - 1;
                while (left < right) {
                    int sum = nums[k] + nums[i] + nums[left] + nums[right];
                    if (sum > target) {
                        right--;
                    } else if (sum < target) {
                        left++;
                    } else {
                        result.add(Arrays.asList(nums[k], nums[i], nums[left], nums[right]));
                        while (left < right && nums[right] == nums[right-1]) {
                            right--;
                        }
                        while (left < right && nums[left] == nums[left+1]) {
                            left++;
                        }
                        right--;
                        left++;
                    }
                }
            }
        }
        return result;
    }
}
  • 15
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@晴天_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值