数组计算两数之和,三数之和,四数之和

这种计算几个数据之和的题目,
一般分为

  1. 在同一个数组中计算几个数之和等于某一个值。
  2. 还有一种是给几个数组,每个数组中取一个数据,让你算几个数之和等于某一个值。
    一般情况下,第二中的难度会更大,因为去重会比较麻烦。

如:
1. 两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

题解:

  • 这个比较简单,用set集合就可以了,每次都判断集合中是否有数据可以满足当前数据+它等于target。

454. 四数相加 II
给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0。

为了使问题简单化,所有的 A, B, C, D 具有相同的长度 N,且 0 ≤ N ≤ 500 。所有整数的范围在 -228 到 228 - 1 之间,最终结果不会超过 231 - 1 。

题解:

  • 这道题算是比较简单的,可以使用HashMap来进行求解。
  • 首先求数组A,B的和,把所有可能的值都存在HashMap里面,key存值,value存出现的次数。
  • 在第二次求数组C和D的和的时候,直接把拿和去存A,B的和的HashMap里面求是否存在值,存在就让count加上该值出现的次数,也就是对应的value。(因为只要下标不一样,就不算重复)
  • 最后遍历完输出count就行了。
    代码:
class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        int length=nums1.length;
        HashMap<Integer,Integer> map1=new HashMap<>();
        Integer temp=0;
        int count=0;
        for(int i=0;i<length;i++){
            for(int j=0;j<length;j++){
                temp=nums1[i]+nums2[j];
                if(map1.containsKey(temp)){
                    int num=map1.get(temp);
                    map1.replace(temp,num+1);
                }else{
                    map1.put(temp,1);
                }
            }
        }
        for(int i=0;i<length;i++){
            for(int j=0;j<length;j++){
                temp=nums3[i]+nums4[j];
                if(map1.containsKey(-temp)){
                    int num=map1.get(-temp);
                    count=count+num;
                }
            }
        }
        return count;
    }
}

15. 三数之和
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

题解:
解法一

  1. 也可以使用HashMap,先两层for循环,这样就确定了a,b。然后再在HashMap里面判断是否存在0-(a+b)就行。
  2. 然后把符合条件的情况存起来,再做去重,不过这样去重的操作比较复杂,不推荐。

解法二

  1. 可以使用双指针,
  2. 先排序
  3. 一层循环,把其中一个值确定下来。
  4. 然后里面一个while循环,然后双指针一个left指向确定值的下一个值,一个right指向最后一个。
  5. 然后根据三者的和与target的结果对比,移动指针,当left>=right的时候退出循环。
  6. 还有一步就是需要去重,首先给i去重。可以通过检测相邻的数据是否一样来进行去重。
  7. 但是不能一开始就去重,这样可能会导致把类似于(-1)+(-1)+2=0的情况忽略。因此需要先用当前值运行一次,然后再去重。
  8. 也就是每次进行去重操作之前都用短路与,前面条件是i>0,这样确保i第一次取值的情况不会被忽略。
  9. 最后两个指针的去重,只需要在每次找到符合条件的元组的时候进行就可以了,其他数据不会进入结果集,因此不需要去重也没事。
    代码:
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> lists=new ArrayList<List<Integer>>();
        if(nums.length<3){
            return lists;
        }
        Arrays.sort(nums);
        for(int i=0;i<nums.length;i++){
            if(nums[i]>0){
                break;
            }
            if(i>0 && nums[i]==nums[i-1]){//i去重
                continue;
            }
            int j=i+1;
            int k=nums.length-1;
            while(j<k){
                int temp=nums[i]+nums[j]+nums[k];
                if(temp==0){
                    List<Integer> list=new ArrayList<Integer>();
                    list.add(nums[i]);
                    list.add(nums[j]);
                    list.add(nums[k]);
                    lists.add(list);//后面两个指针的去重只有在找到一个符合的三元组之后
                                    //才需要把可能一样是这个三元组的重复部分去掉
                    while(k>j&&nums[k]==nums[k-1]){
                        k--;
                    }
                    while(j<k&&nums[j]==nums[j+1]){
                        j++;
                    }
                    k--;
                    j++;
                }else if(temp>0){
                    k--;
                }else{   
                    j++;   
                }
            }
        }
        return lists;
    }
}

18. 四数之和
给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。

注意:答案中不可以包含重复的四元组。

题解:

  1. 该题和上一题的思路差不多,先固定两位,剩下两位使用双指针,去重套路也差不多。

不啰嗦了,直接放代码:

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> lists=new ArrayList<List<Integer>>();
        Arrays.sort(nums);
        for(int i=0;i<nums.length;i++){
            if(nums[i]>0&&nums[i]>target){
                return lists;
            }
            if(i>0&&nums[i]==nums[i-1]){//i去重
                continue;
            }
            for(int j=i+1;j<nums.length;j++){
                int k=j+1;
                if(j>i+1&&nums[j]==nums[j-1]){//j去重,防止把一开始的第一次数据都去了,所以
                //需要等j进入了第一次循环之后才开始去重。
                    continue;
                }
                int l=nums.length-1;
                while(k<l){
                    int temp=nums[i]+nums[j]+nums[k]+nums[l];
                    if(temp==target){
                        List<Integer> list=new ArrayList<>();
                        list.add(nums[i]);
                        list.add(nums[j]);
                        list.add(nums[k]);
                        list.add(nums[l]);
                        while(k<l&&nums[k]==nums[k+1])k++;//k,l去重
                        while(k<l&&nums[l]==nums[l-1])l--;
                        k++;
                        l--;
                        lists.add(list);
                    }else if(temp>target){
                        l--;
                    }else{
                        k++;
                    }
                }
            }
            
        }
        return lists;
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值