代码随想录day07|Leetcode 454四数相加|15 三数之和|18四数之和

LeetCode 454 四数相加

这题因为每个数组中的元素的个数都是相同的,所以我们可以尝试通过hashmap 的方式来解题。

本题解题步骤:

  1. 首先定义 一个unordered_map,key放a和b两数之和,value 放a和b两数之和出现的次数。
  2. 遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到map中。
  3. 定义int变量count,用来统计 a+b+c+d = 0 出现的次数。
  4. 在遍历大C和大D数组,找到如果 0-(c+d) 在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。
  5. 最后返回统计值 count 就可以了
class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        int res=0;
        HashMap<Integer,Integer> map = new HashMap<>();
        for(int i:nums1){
            for(int j:nums2){
                int sum = i+j;
                map.put(sum,map.getOrDefault(sum,0)+1);
            }
        }
        for(int m:nums3){
            for(int n:nums4){
                res+=map.getOrDefault(0-m-n,0);
            }
        }
        return res;
    }
}

LeetCode 15 三数之和

三数之和问题我们一般通过双指针的方式来解决。我们设置三个指针:i,left,right,这三个指针分别对应a,b,c三个值。我们可以通过i来遍历整个数组,left和right分别为i+1和n-1。我们需要对整个数组先进行一个排序,这样对于每一个i的值,我们可以根据abc和的不同来更改left和right的大小。

如果a+b+c>0,那么我们减小right;

如果a+b+c<0,那么我们增加left;

如果等于0,增加到结果中去。

这题主要复杂的地方在于去重,因为题目要求结果不能重复:即便一个数组为{-1,-1,-1,-1,-1,2,2}我们的结果也只有一个{-1,-1,2}虽然我们可以取到不同的-1;但是对于结果数组来说它们完全相同,所以我们要对这种情况进行区分。

对于a的去重:
在我们对i进行遍历时我们发现,如果i此时的结果和i的前一位相同,那么对于a的值来说不会有任何变化,且对于我们之后left和right的范围为前一种情况的子集,举个例子:

{-1,-1,0,1,2,3,4}

当a为第一个-1时,left和right的取值区间为{-1,0,1,2,3,4}

当a为第二个-1时,left和right的取值区间为{0,1,2,3,4}

第二种情况下所有有可能满足条件的解都会包含在第一种情况之中,所以我们可以直接惊醒跳过

对于b和c的去重:

在i固定的情况下,当我们已经确定了一个结果,比如说{-1,-1,-1,-1,2,2}这种情况下:

如果i为第一个-1,left为第二个-1,right为最后一个2,这种情况满足a+b+c=0;但是我们发现,left++之后,a+b+c仍然满足题意但是结果重复了即nums[left] == nums[left+1];这种情况下我们对于b进行去重;同理对于right来说如果nums[right]==nums[right--],我们也需要进行一个去重操作

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        Arrays.sort(nums);
        int n = nums.length;
        for(int i=0;i<n-2;i++){
            if (nums[i] > 0) { 
                return res;
            }
            //对a去重
            if(i>0&&nums[i]==nums[i-1]){
                continue;
            }
            int left = i+1;
            int right = n-1;
            while(right>left){
                if(nums[i]+nums[left]+nums[right]>0){
                    right--;
                }else if(nums[i]+nums[left]+nums[right]<0){
                    left++;
                }else{
                    List<Integer> numbers = new ArrayList<>();
                    numbers.add(nums[i]);
                    numbers.add(nums[left]);
                    numbers.add(nums[right]);
                    res.add(numbers);
                    while(right>left&&nums[right]==nums[right-1]) right--;
                    while(right>left&&nums[left]==nums[left+1])left++;
                    left++;
                    right--;
                }
            }
        }
        return res;
    }
}

LeetCode 18 四数之和

基本思路和三数之和相同,但是因为有四个数,所以我们需要在进行一次for循环。

并且对于i和j来说要分别进行去重

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        int n = nums.length;
        List<List<Integer>> res = new ArrayList<>();
        Arrays.sort(nums);
        for(int i=0;i<n;i++){
            if(nums[i]>0&&nums[i]>target){
                return res;
            }
            if(i>0&&nums[i]==nums[i-1]){
                continue;
            }
            for(int j=i+1;j<n;j++){
                if(j>i+1&&nums[j]==nums[j-1]){
                    continue;
                }
                int left = j+1;
                int right = n-1;
                while(right>left){
                    long sum = (long)nums[i]+nums[j]+nums[left]+nums[right];
                    if(sum>target){
                        right--;
                    }else if(sum<target){
                        left++;
                    }else{
                        res.add(Arrays.asList(nums[i],nums[j],nums[left],nums[right]));
                        while(right>left&&nums[right]==nums[right-1]) right--;
                        while(right>left&&nums[left]==nums[left+1]) left++;
                        left++;
                        right--;
                    }
                }
                
            }
        }
        return res;
    }
}

总结:

HashMap和Set是我们在日常代码中使用的非常多的两种类型。我们需要考虑在不同的情况应该使用什么样的数据结构。

当我们需要比较两个字符串中所包含的字母是否完全相同时(字符串中只含有小写字母),我们可以通过数组的形式来储存数据。

Set可以用来判断是否存在某个元素,而Map则可以通过<key,value>的形式来对数据进行储存

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值