Skip to content

Commit 84fa776

Browse files
committed
923. 3Sum With Multiplicity (Sorting & Two Pointers)
1 parent 29ac15a commit 84fa776

File tree

1 file changed

+76
-0
lines changed

1 file changed

+76
-0
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package com.cheehwatang.leetcode;
2+
3+
import java.util.Arrays;
4+
5+
// Time Complexity : O(n^2),
6+
// where 'n' is the length of 'arr'.
7+
// We traverse 'arr'. With each 'arr[i]', we use two pointers to traverse to find the triplets.
8+
// Arrays.sort() function has a time complexity of O(n logn).
9+
//
10+
// Space Complexity : O(1),
11+
// as the auxiliary space used is independent of the input 'arr'.
12+
13+
public class ThreeSumWithMultiplicity_Sorting_TwoPointers {
14+
15+
// Approach:
16+
// Using sorting and two pointers to traverse the sorted array and check each number if they sum to 'target'.
17+
// Note that, i < j < k and arr[i] + arr[j] + arr[k] == target,
18+
// do not require the index as the sum is not dependent on the index, so sorting is fine.
19+
20+
public int threeSumMulti(int[] arr, int target) {
21+
int n = arr.length;
22+
Arrays.sort(arr);
23+
long count = 0;
24+
25+
// With each 'i', use two pointers 'j' and 'k' to traverse the remaining numbers to the right of 'i'.
26+
for (int i = 0; i < n - 2; i++) {
27+
// If the smallest number is greater than 'target',
28+
// then the remaining numbers (which are greater) are impossible to sum to be equal to 'target'.
29+
if (arr[i] + arr[i + 1] + arr[i + 2] > target) break;
30+
// If the largest number is less than 'target', meaning we need to increase 'i' to get a larger number.
31+
if (arr[i] + arr[n - 1] + arr[n - 2] < target) continue;
32+
33+
// After the check, traverse with 'j' and 'k' from both ends.
34+
int j = i + 1;
35+
int k = n - 1;
36+
while (j < k) {
37+
int sum = arr[i] + arr[j] + arr[k];
38+
// Move 'j' to right if sum is less than target.
39+
if (sum < target) j++;
40+
// Move 'k' to left if sum is greater than target.
41+
else if (sum > target) k--;
42+
// If it is equal, keep track of the frequency for both 'arr[j]' and 'arr[k]'.
43+
else {
44+
int countJ = 1;
45+
while (j < k && arr[j] == arr[j + 1]) {
46+
j++;
47+
countJ++;
48+
}
49+
int countK = 1;
50+
while (j < k && arr[k] == arr[k - 1]) {
51+
k--;
52+
countK++;
53+
}
54+
// If both are same, get the geometric sum for 'countJ' + 'countK' - 1.
55+
// Example: [1,2,2,2,2], target = 5. With arr[i] = 1, arr[j] == arr[k] = 2.
56+
// Note that the "j < k" will break with 'j' overlapping with 'k'.
57+
// Thus, 'countJ' = 4 and 'countK' = 1.
58+
// 'countJ' + 'countK' - 1 = 4, which results in 4 * 3 / 2 = 6 possible combinations.
59+
if (arr[j] == arr[k]) {
60+
int frequency = countJ + countK - 1;
61+
count += (long) frequency * (frequency - 1) / 2;
62+
}
63+
// If they are different, the count increase by the multiplication for both.
64+
// Example: [1,2,2,3,3], target = 6. With arr[i] = 1, arr[j] = 2 and arr[k] = 3.
65+
// There are 2 * 2 = 4 possible combinations for the 2 and 3.
66+
else
67+
count += (long) countJ * countK;
68+
// Once done, move both pointers to continue check the other numbers.
69+
j++;
70+
k--;
71+
}
72+
}
73+
}
74+
return (int) (count % (1e9 + 7));
75+
}
76+
}

0 commit comments

Comments
 (0)