Welcome to Subscribe On Youtube
Formatted question description: https://leetcode.ca/all/454.html
454. 4Sum II (Medium)
Given four lists A, B, C, D of integer values, compute how many tuples (i, j, k, l)
there are such that A[i] + B[j] + C[k] + D[l]
is zero.
To make problem a bit easier, all A, B, C, D have same length of N where 0 ≤ N ≤ 500. All integers are in the range of -228 to 228 - 1 and the result is guaranteed to be at most 231 - 1.
Example:
Input: A = [ 1, 2] B = [-2,-1] C = [-1, 2] D = [ 0, 2] Output: 2 Explanation: The two tuples are: 1. (0, 0, 0, 1) -> A[0] + B[0] + C[0] + D[1] = 1 + (-2) + (-1) + 2 = 0 2. (1, 1, 0, 0) -> A[1] + B[1] + C[0] + D[0] = 2 + (-1) + (-1) + 0 = 0
Related Topics:
Hash Table, Binary Search
Similar Questions:
Solution 1. Map + Bi-directional Search
Use map to store the counts of different sums in AB
and CD
. Use two pointers one from smallest in AB
going to greater values, and the other one from greatest in CD
to smaller values. Whenever found a pair summing to 0, add count1 * count2
to the result.
Time complexity
The sum
function iterates through O(N^2)
pairs and accessing the map
at most take O(log(N^2))=O(logN)
time. So the sum
takes O(N^2 * logN)
time.
Each map
has O(N^2)
data in the worst case and the bi-directional search only traverse each map once at most, so the searching takes O(N^2)
time.
So, overall it takes O(N^2 * logN)
time.
-
class Solution { public int fourSumCount(int[] A, int[] B, int[] C, int[] D) { int count = 0; // 2sum => occurence Map<Integer, Integer> sumCountMap = new HashMap<Integer, Integer>(); int length = A.length; for (int i = 0; i < length; i++) { for (int j = 0; j < length; j++) { int sumAB = A[i] + B[j]; int countAB = sumCountMap.getOrDefault(sumAB, 0); countAB++; sumCountMap.put(sumAB, countAB); } } for (int i = 0; i < length; i++) { for (int j = 0; j < length; j++) { int sumCD = C[i] + D[j]; int curCount = sumCountMap.getOrDefault(-sumCD, 0); count += curCount; } } return count; } } ############ class Solution { public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) { Map<Integer, Integer> counter = new HashMap<>(); for (int a : nums1) { for (int b : nums2) { counter.put(a + b, counter.getOrDefault(a + b, 0) + 1); } } int ans = 0; for (int c : nums3) { for (int d : nums4) { ans += counter.getOrDefault(-(c + d), 0); } } return ans; } }
-
// OJ: https://leetcode.com/problems/4sum-ii // Time: O(N^2 * logN) // Space: O(N^2) class Solution { private: void sum(vector<int> &A, vector<int> &B, map<int, int> &m) { for (auto a : A) { for (auto b : B) m[a + b]++; } } public: int fourSumCount(vector<int>& A, vector<int>& B, vector<int>& C, vector<int>& D) { map<int, int> a, b; sum(A, B, a); sum(C, D, b); auto i = a.begin(); auto j = b.rbegin(); int ans = 0; while (i != a.end() && j != b.rend()) { if (i->first + j->first == 0) { ans += i->second * j->second; ++i; ++j; } else if (i->first + j->first < 0) ++i; else ++j; } return ans; } };
-
from collections import Counter class Solution: def fourSumCount( self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int] ) -> int: cnt = Counter(a + b for a in nums1 for b in nums2) return sum(cnt[-(c + d)] for c in nums3 for d in nums4) ############ class Solution: def fourSumCount( self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int] ) -> int: counter = Counter() for a in nums1: for b in nums2: counter[a + b] += 1 ans = 0 for c in nums3: for d in nums4: # adding for every time -(c+d) ans += counter[-(c + d)] return ans ############ class Solution(object): def fourSumCount(self, A, B, C, D): """ :type A: List[int] :type B: List[int] :type C: List[int] :type D: List[int] :rtype: int """ ans = 0 abDict = {} for i in range(len(A)): for j in range(len(B)): if A[i] + B[j] not in abDict: abDict[A[i] + B[j]] = 1 else: abDict[A[i] + B[j]] += 1 for i in range(len(C)): for j in range(len(D)): if -C[i] - D[j] in abDict: ans += abDict[-C[i] - D[j]] return ans
-
func fourSumCount(nums1 []int, nums2 []int, nums3 []int, nums4 []int) int { counter := make(map[int]int) for _, a := range nums1 { for _, b := range nums2 { counter[a+b]++ } } ans := 0 for _, c := range nums3 { for _, d := range nums4 { ans += counter[-(c + d)] } } return ans }
-
function fourSumCount( nums1: number[], nums2: number[], nums3: number[], nums4: number[], ): number { const cnt: Map<number, number> = new Map(); for (const a of nums1) { for (const b of nums2) { const x = a + b; cnt.set(x, (cnt.get(x) || 0) + 1); } } let ans = 0; for (const c of nums3) { for (const d of nums4) { const x = c + d; ans += cnt.get(-x) || 0; } } return ans; }
-
use std::collections::HashMap; impl Solution { pub fn four_sum_count( nums1: Vec<i32>, nums2: Vec<i32>, nums3: Vec<i32>, nums4: Vec<i32> ) -> i32 { let mut cnt = HashMap::new(); for &a in &nums1 { for &b in &nums2 { *cnt.entry(a + b).or_insert(0) += 1; } } let mut ans = 0; for &c in &nums3 { for &d in &nums4 { if let Some(&count) = cnt.get(&(0 - (c + d))) { ans += count; } } } ans } }