How to solve Leetcode 923. 3Sum With Multiplicity

How to solve Leetcode 923. 3Sum With Multiplicity

Problem statement

Given an integer array arr, and an integer target, return the number of tuples i, j, k such that i < j < k and arr[i] + arr[j] + arr[k] == target.

As the answer can be very large, return it modulo 10^9 + 7.

Example 1

Input: arr = [1,1,2,2,3,3,4,4,5,5], target = 8
Output: 20
Explanation: 
Enumerating by the values (arr[i], arr[j], arr[k]):
(1, 2, 5) occurs 8 times;
(1, 3, 4) occurs 8 times;
(2, 2, 4) occurs 2 times;
(2, 3, 3) occurs 2 times.

Example 2

Input: arr = [1,1,2,2,2,2], target = 5
Output: 12
Explanation: 
arr[i] = 1, arr[j] = arr[k] = 2 occurs 12 times:
We choose one 1 from [1,1] in 2 ways,
and two 2s from [2,2,2,2] in 6 ways.

Constraints

  • 3 <= arr.length <= 3000.
  • 0 <= arr[i] <= 100.
  • 0 <= target <= 300.

Solution 1: Bruteforce

Find all tuples that satisfy the target sum.

Code

#include <vector>
#include <iostream>
using namespace std;
int threeSumMulti(vector<int>& arr, int target) {
    const int MOD = 1000000007;
    int count = 0;
    for (int i = 0; i < arr.size() - 2; i++) {
        for (int j = i + 1; j < arr.size() - 1; j++) {
            for (int k = j + 1; k < arr.size(); k++) {
                if (arr[i] + arr[j] + arr[k] == target) {
                    count += 1 % MOD;
                }
            }
        }
    }
    return count;
}
int main() {
    vector<int> arr{1,1,2,2,3,3,4,4,5,5};
    cout << threeSumMulti(arr, 8) << endl;
    arr = {1,1,2,2,2,2};
    cout << threeSumMulti(arr, 5) << endl;
}
Output:
20
12

Complexity

  • Runtime: O(N^3), where N = arr.length.
  • Extra space: O(1).

Solution 2: Store one of the values in the tuples

Rewrite the condition arr[i] + arr[j] + arr[k] == target as arr[i] == target - arr[j] - arr[k], then you can reduce one of the for loops by using a map to store the count of the values arr[i] that have been visited.

Code

#include <vector>
#include <iostream>
#include <unordered_map>
using namespace std;
int threeSumMulti(vector<int>& arr, int target) {
    unordered_map<int, int> m;
    const int MOD = 1000000007;
    int count = 0;
    for (int i = 0; i < arr.size() - 1; i++) {
        for (int j = i + 1; j < arr.size(); j++) {
            auto it = m.find(target - arr[i] - arr[j]);
            if (it != m.end()) {
                count = (count + it->second) % MOD;
            }
        }
        m[arr[i]]++;
    }
    return count;
}
int main() {
    vector<int> arr{1,1,2,2,3,3,4,4,5,5};
    cout << threeSumMulti(arr, 8) << endl;
    arr = {1,1,2,2,2,2};
    cout << threeSumMulti(arr, 5) << endl;
}
Output:
20
12

Complexity

  • Runtime: O(N^2), where N = arr.length.
  • Extra space: O(N).