• 力扣刷题日记——哈希


    四数相加 II

    在这里插入图片描述

    首先定义 一个unordered_map,key放a和b两数之和,value 放a和b两数之和出现的次数。
    遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到map中。
    定义int变量count,用来统计 a+b+c+d = 0 出现的次数。
    在遍历大C和大D数组,找到如果 0-(c+d) 在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。
    最后返回统计值 count 就可以了

    class Solution {
        public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
     Map<Integer, Integer> map = new HashMap<>();
            int temp;
            int res = 0;
            //统计两个数组中的元素之和,同时统计出现的次数,放入map
            for (int i : nums1) {
                for (int j : nums2) {
                    temp = i + j;
                    if (map.containsKey(temp)) {
                        map.put(temp, map.get(temp) + 1);
                    } else {
                        map.put(temp, 1);
                    }
                }
            }
            //统计剩余的两个元素的和,在map中找是否存在相加为0的情况,同时记录次数
            for (int i : nums3) {
                for (int j : nums4) {
                    temp = i + j;
                    if (map.containsKey(0 - temp)) {
                        res += map.get(0 - temp);
                    }
                }
            }
            return res;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    三数之和

    在这里插入图片描述

    首先将数组排序,然后有一层for循环,i从下标0的地方开始,同时定一个下标left 定义在i+1的位置上,定义下标right 在数组结尾的位置上。
    依然还是在数组中找到 abc 使得a + b +c =0,我们这里相当于 a = nums[i],b = nums[left],c = nums[right]。
    接下来如何移动left 和right呢, 如果nums[i] + nums[left] + nums[right] > 0 就说明 此时三数之和大了,因为数组是排序后了,所以right下标就应该向左移动,这样才能让三数之和小一些。
    如果 nums[i] + nums[left] + nums[right] < 0 说明 此时 三数之和小了,left 就向右移动,才能让三数之和大一些,直到left与right相遇为止。

    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++) {
                if (nums[i] > 0) {
                    return result;
                }
    
                if (i > 0 && nums[i] == nums[i - 1]) {
                    continue;
                }
    
                int left = i + 1;
                int right = nums.length - 1;
                while (right > left) {
                    int sum = nums[i] + nums[left] + nums[right];
                    if (sum > 0) {
                        right--;
                    } else if (sum < 0) {
                        left++;
                    } else {
                        result.add(Arrays.asList(nums[i], nums[left], nums[right]));
    
                        while (right > left && nums[right] == nums[right - 1]) right--;
                        while (right > left && nums[left] == nums[left + 1]) left++;
                        
                        right--; 
                        left++;
                    }
                }
            }
            return result;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    四数之和

    在这里插入图片描述

    四数之和的双指针解法是两层for循环nums[k] + nums[i]为确定值,依然是循环内有left和right下标作为双指针,找出nums[k] + nums[i] + nums[left] + nums[right] == target的情况,三数之和的时间复杂度是O(n^2),四数之和的时间复杂度是O(n ^3) 。

    class Solution {
        public List<List<Integer>> fourSum(int[] nums, int target) {
             List<List<Integer>> result = new ArrayList<>();
            Arrays.sort(nums);
           
            for (int i = 0; i < nums.length; i++) {
    
                // nums[i] > target 直接返回, 剪枝操作
                if (nums[i] > 0 && nums[i] > target) {
                    return result;
                }
    
                if (i > 0 && nums[i - 1] == nums[i]) {
                    continue;
                }
                
                for (int j = i + 1; j < nums.length; j++) {
    
                    if (j > i + 1 && nums[j - 1] == nums[j]) {
                        continue;
                    }
    
                    int left = j + 1;
                    int right = nums.length - 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 {
                            result.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 result;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
  • 相关阅读:
    C语言学习之路(基础篇)—— 数据类型 02
    OSCP系列靶场-Esay-Moneybox保姆级
    Java泛型的协变与逆变
    Spring Boot中发送邮件时,如何让发件人显示别名
    又一超好用的 Python 数据处理工具 Mito 前来报到
    【C语言】指针经典笔试题(上)
    一文搞定接口幂等性架构设计方案
    改变开发的未来 | 探索无服务器与人工智能的协同效应
    101道算法javaScript描述【一】
    从bootstrap源码中学习Sass(一)
  • 原文地址:https://blog.csdn.net/crisp0530/article/details/126843928