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:

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
        }
    }
    
    

All Problems

All Solutions