|
| 1 | +--- |
| 2 | +id: 3sum-with-multiplicity |
| 3 | +title: Three Sum With Multiplicity |
| 4 | +sidebar_label: 3Sum-with-multiplicity |
| 5 | +tags: |
| 6 | + - Array |
| 7 | + - Hash Map |
| 8 | + - Combinatorics |
| 9 | + - Two Pointers |
| 10 | +--- |
| 11 | + |
| 12 | +## Problem Description |
| 13 | + |
| 14 | +| Problem Statement | Solution Link | LeetCode Profile | |
| 15 | +| :------------------------------------------------------ | :------------------------------------------------------------------------- | :------------------------------------------------------ | |
| 16 | +| [3sum-with-multiplicity](https://leetcode.com/problems/3sum-with-multiplicity/description/) | [3sum-with-multiplicity Solution on LeetCode](https://leetcode.com/problems/3sum-with-multiplicity/solutions/) | [Nikita Saini](https://leetcode.com/u/Saini_Nikita/) | |
| 17 | +## Problem Description |
| 18 | + |
| 19 | +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`. |
| 20 | + |
| 21 | +As the answer can be very large, return it modulo 10^9 + 7. |
| 22 | + |
| 23 | +### Example 1: |
| 24 | +**Input:** `arr = [1, 1, 2, 2, 3, 3, 4, 4, 5, 5], target = 8` |
| 25 | +**Output:** `20` |
| 26 | +**Explanation:** |
| 27 | +`Enumerating by the values (arr[i], arr[j], arr[k]): |
| 28 | +(1, 2, 5) occurs 8 times; |
| 29 | +(1, 3, 4) occurs 8 times; |
| 30 | +(2, 2, 4) occurs 2 times; |
| 31 | +(2, 3, 3) occurs 2 times.` |
| 32 | + |
| 33 | +### Example 2: |
| 34 | +**Input:** `arr = [1, 1, 2, 2, 2, 2], target = 5` |
| 35 | +**Output:** `12` |
| 36 | +**Explanation:** |
| 37 | +`arr[i] = 1, arr[j] = arr[k] = 2 occurs 12 times: |
| 38 | +We choose one 1 from [1,1] in 2 ways, |
| 39 | +and two 2s from [2,2,2,2] in 6 ways.` |
| 40 | + |
| 41 | +### Example 3: |
| 42 | +**Input:** `arr = [2, 1, 3], target = 6` |
| 43 | +**Output:** `1` |
| 44 | +**Explanation:** `(1, 2, 3) occurred one time in the array so we return 1.` |
| 45 | + |
| 46 | +### Constraints: |
| 47 | +- `3 <= arr.length <= 3000` |
| 48 | +- `0 <= arr[i] <= 100` |
| 49 | +- `0 <= target <= 300` |
| 50 | + |
| 51 | +## Approach |
| 52 | + |
| 53 | +To solve this problem, we can use a combination of counting and two-pointer techniques. Here is a step-by-step approach: |
| 54 | + |
| 55 | +1. **Count the Occurrences**: Use a hashmap to count the occurrences of each element in the array. |
| 56 | +2. **Find Triplets**: Iterate over each pair of elements and check if the third element needed to reach the target exists in the hashmap. |
| 57 | +3. **Handle Different Cases**: Depending on the values of the three elements, handle different counting cases (all three equal, two equal, all different). |
| 58 | +4. **Modulo Operation**: Use modulo 10^9 + 7 to ensure the result doesn't overflow. |
| 59 | + |
| 60 | +## Solution |
| 61 | + |
| 62 | +### Python |
| 63 | +```python |
| 64 | +from collections import Counter |
| 65 | + |
| 66 | +class Solution: |
| 67 | + def threeSumMulti(self, arr, target): |
| 68 | + MOD = 10**9 + 7 |
| 69 | + count = Counter(arr) |
| 70 | + keys = sorted(count) |
| 71 | + result = 0 |
| 72 | + |
| 73 | + for i, x in enumerate(keys): |
| 74 | + T = target - x |
| 75 | + j, k = i, len(keys) - 1 |
| 76 | + while j <= k: |
| 77 | + y, z = keys[j], keys[k] |
| 78 | + if y + z < T: |
| 79 | + j += 1 |
| 80 | + elif y + z > T: |
| 81 | + k -= 1 |
| 82 | + else: |
| 83 | + if i < j < k: |
| 84 | + result += count[x] * count[y] * count[z] |
| 85 | + elif i == j < k: |
| 86 | + result += count[x] * (count[x] - 1) // 2 * count[z] |
| 87 | + elif i < j == k: |
| 88 | + result += count[x] * count[y] * (count[y] - 1) // 2 |
| 89 | + else: # i == j == k |
| 90 | + result += count[x] * (count[x] - 1) * (count[x] - 2) // 6 |
| 91 | + result %= MOD |
| 92 | + j += 1 |
| 93 | + k -= 1 |
| 94 | + |
| 95 | + return result |
| 96 | +``` |
| 97 | + |
| 98 | +### Java |
| 99 | +```java |
| 100 | +import java.util.HashMap; |
| 101 | +import java.util.Map; |
| 102 | + |
| 103 | +class Solution { |
| 104 | + public int threeSumMulti(int[] arr, int target) { |
| 105 | + int MOD = 1_000_000_007; |
| 106 | + Map<Integer, Long> count = new HashMap<>(); |
| 107 | + |
| 108 | + for (int num : arr) { |
| 109 | + count.put(num, count.getOrDefault(num, 0L) + 1); |
| 110 | + } |
| 111 | + |
| 112 | + long result = 0; |
| 113 | + |
| 114 | + for (int i : count.keySet()) { |
| 115 | + for (int j : count.keySet()) { |
| 116 | + int k = target - i - j; |
| 117 | + if (count.containsKey(k)) { |
| 118 | + long ci = count.get(i); |
| 119 | + long cj = count.get(j); |
| 120 | + long ck = count.get(k); |
| 121 | + |
| 122 | + if (i == j && j == k) { |
| 123 | + result += ci * (ci - 1) * (ci - 2) / 6; // C(ci, 3) |
| 124 | + } else if (i == j && j != k) { |
| 125 | + result += ci * (ci - 1) / 2 * ck; // C(ci, 2) * ck |
| 126 | + } else if (i < j && j < k) { |
| 127 | + result += ci * cj * ck; // ci * cj * ck |
| 128 | + } |
| 129 | + } |
| 130 | + } |
| 131 | + } |
| 132 | + |
| 133 | + return (int)(result % MOD); |
| 134 | + } |
| 135 | +} |
| 136 | +``` |
| 137 | + |
| 138 | +### C++ |
| 139 | +```cpp |
| 140 | +#include <vector> |
| 141 | +#include <unordered_map> |
| 142 | + |
| 143 | +using namespace std; |
| 144 | + |
| 145 | +class Solution { |
| 146 | +public: |
| 147 | + int threeSumMulti(vector<int>& arr, int target) { |
| 148 | + const int MOD = 1'000'000'007; |
| 149 | + unordered_map<int, long> count; |
| 150 | + |
| 151 | + for (int num : arr) { |
| 152 | + count[num]++; |
| 153 | + } |
| 154 | + |
| 155 | + long result = 0; |
| 156 | + |
| 157 | + for (auto i : count) { |
| 158 | + for (auto j : count) { |
| 159 | + int k = target - i.first - j.first; |
| 160 | + if (count.find(k) != count.end()) { |
| 161 | + long ci = i.second; |
| 162 | + long cj = j.second; |
| 163 | + long ck = count[k]; |
| 164 | + |
| 165 | + if (i.first == j.first && j.first == k) { |
| 166 | + result += ci * (ci - 1) * (ci - 2) / 6; |
| 167 | + } else if (i.first == j.first && j.first != k) { |
| 168 | + result += ci * (ci - 1) / 2 * ck; |
| 169 | + } else if (i.first < j.first && j.first < k) { |
| 170 | + result += ci * cj * ck; |
| 171 | + } |
| 172 | + } |
| 173 | + } |
| 174 | + } |
| 175 | + |
| 176 | + return result % MOD; |
| 177 | + } |
| 178 | +}; |
| 179 | +``` |
| 180 | +
|
| 181 | +### C |
| 182 | +```c |
| 183 | +#include <stdio.h> |
| 184 | +#include <stdlib.h> |
| 185 | +
|
| 186 | +#define MOD 1000000007 |
| 187 | +
|
| 188 | +typedef struct { |
| 189 | + int key; |
| 190 | + long value; |
| 191 | +} HashMap; |
| 192 | +
|
| 193 | +int compare(const void *a, const void *b) { |
| 194 | + return ((HashMap *)a)->key - ((HashMap *)b)->key; |
| 195 | +} |
| 196 | +
|
| 197 | +int threeSumMulti(int* arr, int arrSize, int target) { |
| 198 | + HashMap count[101] = {0}; |
| 199 | + int countSize = 0; |
| 200 | + |
| 201 | + for (int i = 0; i < arrSize; i++) { |
| 202 | + count[arr[i]].key = arr[i]; |
| 203 | + count[arr[i]].value++; |
| 204 | + } |
| 205 | + |
| 206 | + for (int i = 0; i <= 100; i++) { |
| 207 | + if (count[i].value > 0) { |
| 208 | + count[countSize++] = count[i]; |
| 209 | + } |
| 210 | + } |
| 211 | + |
| 212 | + qsort(count, countSize, sizeof(HashMap), compare); |
| 213 | + |
| 214 | + long result = 0; |
| 215 | + |
| 216 | + for (int i = 0; i < countSize; i++) { |
| 217 | + for (int j = i; j < countSize; j++) { |
| 218 | + int k = target - count[i].key - count[j].key; |
| 219 | + if (k < 0 || k > 100 || count[k].value == 0) continue; |
| 220 | + |
| 221 | + if (count[i].key == count[j].key && count[j].key == k) { |
| 222 | + result += count[i].value * (count[i].value - 1) * (count[i].value - 2) / 6; |
| 223 | + } else if (count[i].key == count[j].key && count[j].key != k) { |
| 224 | + result += count[i].value * (count[i].value - 1) / 2 * count[k].value; |
| 225 | + } else if (count[i].key < count[j].key && count[j].key < k) { |
| 226 | + result += count[i].value * count[j].value * count[k].value; |
| 227 | + } |
| 228 | + |
| 229 | + result %= MOD; |
| 230 | + } |
| 231 | + } |
| 232 | + |
| 233 | + return result; |
| 234 | +} |
| 235 | +``` |
| 236 | + |
| 237 | +### JavaScript |
| 238 | +```javascript |
| 239 | +var threeSumMulti = function(arr, target) { |
| 240 | + const MOD = 1e9 + 7; |
| 241 | + let count = new Map(); |
| 242 | + |
| 243 | + for (let num of arr) { |
| 244 | + count.set(num, (count.get(num) || 0) + 1); |
| 245 | + } |
| 246 | + |
| 247 | + let keys = Array.from(count.keys()).sort((a, b) => a - b); |
| 248 | + let result = 0; |
| 249 | + |
| 250 | + for (let i = 0; i < keys.length; i++) { |
| 251 | + let x = keys[i]; |
| 252 | + let T = target - x; |
| 253 | + let j = i, k = keys.length - 1; |
| 254 | + |
| 255 | + while (j <= k) { |
| 256 | + let y = keys[j], z = keys[k]; |
| 257 | + if ( |
| 258 | + |
| 259 | +y + z < T) { |
| 260 | + j++; |
| 261 | + } else if (y + z > T) { |
| 262 | + k--; |
| 263 | + } else { |
| 264 | + if (i < j && j < k) { |
| 265 | + result += count.get(x) * count.get(y) * count.get(z); |
| 266 | + } else if (i === j && j < k) { |
| 267 | + result += count.get(x) * (count.get(x) - 1) / 2 * count.get(z); |
| 268 | + } else if (i < j && j === k) { |
| 269 | + result += count.get(x) * count.get(y) * (count.get(y) - 1) / 2; |
| 270 | + } else { // i === j === k |
| 271 | + result += count.get(x) * (count.get(x) - 1) * (count.get(x) - 2) / 6; |
| 272 | + } |
| 273 | + result %= MOD; |
| 274 | + j++; |
| 275 | + k--; |
| 276 | + } |
| 277 | + } |
| 278 | + } |
| 279 | + |
| 280 | + return result; |
| 281 | +}; |
| 282 | +``` |
| 283 | + |
| 284 | +## Step by Step Algorithm |
| 285 | + |
| 286 | +1. **Initialize Variables**: Create a hashmap to count the occurrences of each element in the array. |
| 287 | +2. **Count Elements**: Iterate through the array and populate the hashmap with the count of each element. |
| 288 | +3. **Sort Keys**: Sort the unique keys from the hashmap. |
| 289 | +4. **Iterate Over Pairs**: Use a nested loop to iterate over each pair of elements `(i, j)` and calculate the third element `k` needed to reach the target sum. |
| 290 | +5. **Check Existence of k**: Verify if `k` exists in the hashmap. |
| 291 | +6. **Count Triplets**: Depending on the values of `i`, `j`, and `k`, count the valid triplets using combinatorics: |
| 292 | + - All three elements are the same: Use combination formula `C(count, 3)`. |
| 293 | + - Two elements are the same: Use combination formula `C(count, 2) * count`. |
| 294 | + - All three elements are different: Multiply their counts directly. |
| 295 | +7. **Modulo Operation**: Take the result modulo `10^9 + 7` to avoid overflow. |
| 296 | +8. **Return Result**: Return the final count of valid triplets. |
| 297 | + |
| 298 | +## Conclusion |
| 299 | + |
| 300 | +This problem can be efficiently solved using a combination of counting, sorting, and combinatorics. By carefully handling different cases for the triplet elements and using the modulo operation to prevent overflow, we can count the number of valid triplets that sum to the target. |
0 commit comments