哈希表5:四数相加II(454)

本题如下:(链接:https://leetcode.cn/problems/4sum-ii/)

题目:给你四个整数数组 A、B、C 和 D ,数组长度都是 N ,请你计算有多少个元组 (i, j, k, l) 能满足:

A[i] + B[j] + C[k] + D[l] == 0 ,0 <= i, j, k, l < N

 

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

 

 

思路:

本题咋眼一看好像和题库第15题三数之和,第18题四数之和差不多,其实差很多。

本题是使用哈希法的经典题目,而三数之和,四数之和并不合适使用哈希法,因为三数之和和四数之和这两道题目使用哈希法在不超时的情况下做到对结果去重是很困难的,很有多细节需要处理。

而这道题目是四个独立的数组,只要找到A[i] + B[j] + C[k] + D[l] = 0就可以,不用考虑有重复的四个元素相加等于0的情况,所以相对于四数之和和三数之和,还是简单了不少。

如果本题想提升难度:那么可以给出一个数组(而不是四个数组),在这里找出四个元素相加等于0,答案中不可以包含重复的四元组。这里先不讨论这种情况。

 

本题解题步骤:

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 就可以了。

 

这样我们就可以写出本题的C++代码:

 1 class Solution {
 2 public:
 3     int fourSumCount(vector<int>& A, vector<int>& B, vector<int>& C, vector<int>& D) {
 4         unordered_map<int, int> umap; //key:a+b的数值,value:a+b数值出现的次数
 5         // 遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到map中
 6         for (int a : A) {
 7             for (int b : B) {
 8                 umap[a + b]++;
 9             }
10         }
11         int count = 0; // 统计a+b+c+d = 0 出现的次数
12         // 在遍历大C和大D数组,找到如果 0-(c+d) 在map中出现过的话,就把map中key对应的value也就是出现次数统计出来。
13         for (int c : C) {
14             for (int d : D) {
15                 if (umap.find(0 - (c + d)) != umap.end()) {
16                     count += umap[0 - (c + d)];
17                 }
18             }
19         }
20         return count;
21     }
22 };

 

 

接下来给出相应的Java版本:

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

 

posted @ 2022-09-10 17:03  Ricentch  阅读(29)  评论(0)    收藏  举报