Skip to content

Commit a07afec

Browse files
authored
Merge pull request #322 from cheehwatang/add-16-3SumClosest
Add 16. 3Sum Closest
2 parents 25b3c1b + 5e78d83 commit a07afec

File tree

2 files changed

+148
-12
lines changed

2 files changed

+148
-12
lines changed

README.md

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,19 @@
2727
<th>Solution</th>
2828
<th>Topics</th>
2929
</tr>
30+
<tr>
31+
<td align="center">September 1st</td>
32+
<td>16. <a href="https://leetcode.com/problems/3sum-closest/">3Sum Closest</a></td>
33+
<td align="center">$\text{\color{Dandelion}Medium}$</td>
34+
<td align="center">
35+
<a href="https://github.com/cheehwatang/leetcode-java/blob/main/solutions/16.%203Sum%20Closest/ThreeSumClosest.java">Sorting & Two Pointers</a>
36+
</td>
37+
<td align="center">
38+
<a href="#array">Array</a>,
39+
<a href="#sorting">Sorting</a>,
40+
<a href="#two-pointers">Two Pointers</a>
41+
</td>
42+
</tr>
3043
<tr>
3144
<td align="center">August 31st</td>
3245
<td>15. <a href="https://leetcode.com/problems/3sum/">3Sum</a></td>
@@ -76,18 +89,6 @@
7689
<a href="#string">String</a>
7790
</td>
7891
</tr>
79-
<tr>
80-
<td align="center">August 27th</td>
81-
<td>3. <a href="https://leetcode.com/problems/longest-substring-without-repeating-characters/">Longest Substring Without Repeating Characters</a></td>
82-
<td align="center">$\text{\color{Dandelion}Medium}$</td>
83-
<td align="center">
84-
<a href="https://github.com/cheehwatang/leetcode-java/blob/main/solutions/3.%20Longest%20Substring%20Without%20Repeating%20Characters/LongestSubstringWithoutRepeatingCharacters.java">Sliding Window</a>
85-
</td>
86-
<td align="center">
87-
<a href="#sliding-window">Sliding Window</a>,
88-
<a href="#string">String</a>
89-
</td>
90-
</tr>
9192
</table>
9293
</br>
9394
<hr>
@@ -178,6 +179,20 @@
178179
</td>
179180
<td></td>
180181
</tr>
182+
<tr>
183+
<td align="center">16</td>
184+
<td><a href="https://leetcode.com/problems/3sum-closest/">3Sum Closest</a></td>
185+
<td align="center">
186+
<a href="https://github.com/cheehwatang/leetcode-java/blob/main/solutions/16.%203Sum%20Closest/ThreeSumClosest.java">Java</a>
187+
</td>
188+
<td align="center">$\text{\color{Dandelion}Medium}$</td>
189+
<td align="center">
190+
<a href="#array">Array</a>,
191+
<a href="#sorting">Sorting</a>,
192+
<a href="#two-pointers">Two Pointers</a>
193+
</td>
194+
<td></td>
195+
</tr>
181196
<tr>
182197
<td align="center">26</td>
183198
<td><a href="https://leetcode.com/problems/remove-duplicates-from-sorted-array/">Remove Duplicates from Sorted Array</a></td>
@@ -7286,6 +7301,20 @@
72867301
</td>
72877302
<td></td>
72887303
</tr>
7304+
<tr>
7305+
<td align="center">16</td>
7306+
<td><a href="https://leetcode.com/problems/3sum-closest/">3Sum Closest</a></td>
7307+
<td align="center">
7308+
<a href="https://github.com/cheehwatang/leetcode-java/blob/main/solutions/16.%203Sum%20Closest/ThreeSumClosest.java">Java</a>
7309+
</td>
7310+
<td align="center">$\text{\color{Dandelion}Medium}$</td>
7311+
<td align="center">
7312+
<a href="#array">Array</a>,
7313+
<a href="#sorting">Sorting</a>,
7314+
<a href="#two-pointers">Two Pointers</a>
7315+
</td>
7316+
<td></td>
7317+
</tr>
72897318
<tr>
72907319
<td align="center">49</td>
72917320
<td><a href="https://leetcode.com/problems/group-anagrams/">Group Anagrams</a></td>
@@ -9189,6 +9218,20 @@
91899218
</td>
91909219
<td></td>
91919220
</tr>
9221+
<tr>
9222+
<td align="center">16</td>
9223+
<td><a href="https://leetcode.com/problems/3sum-closest/">3Sum Closest</a></td>
9224+
<td align="center">
9225+
<a href="https://github.com/cheehwatang/leetcode-java/blob/main/solutions/16.%203Sum%20Closest/ThreeSumClosest.java">Java</a>
9226+
</td>
9227+
<td align="center">$\text{\color{Dandelion}Medium}$</td>
9228+
<td align="center">
9229+
<a href="#array">Array</a>,
9230+
<a href="#sorting">Sorting</a>,
9231+
<a href="#two-pointers">Two Pointers</a>
9232+
</td>
9233+
<td></td>
9234+
</tr>
91929235
<tr>
91939236
<td align="center">19</td>
91949237
<td><a href="https://leetcode.com/problems/remove-nth-node-from-end-of-list/">Remove Nth Node From End of List</a></td>
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
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 'nums'.
7+
// We traverse 'nums' to check each 'nums[i]', with each element we use 2 pointers,
8+
// thus it is a nested loop, with O(n^2) time complexity.
9+
// The Arrays.sort() function has a time complexity of O(n logn).
10+
//
11+
// Space Complexity : O(1),
12+
// as the auxiliary space used is independent of the input.
13+
14+
public class ThreeSumClosest {
15+
16+
// Approach:
17+
// Use sorting and two pointers to search for all the triplets and check for the closest sum to 'target'.
18+
// For each 'nums[i]' in 'nums', we can check the sum with nums[j] and nums[k] using two pointers,
19+
// 'left' and 'right' to traverse the remaining numbers.
20+
// In order to use two pointers in this manner, we have to first sort the array in ascending order.
21+
// This allows use to check if nums[i] + nums[j] + nums[k] is greater or less than 0.
22+
// If the sum is less than 'target', then we shift the 'left' pointer to the right.
23+
// If the sum is greater than 'target', then we shift the 'right' pointer to the left.
24+
// If we found the sum to be equal to 'target', then we return 'target'.
25+
//
26+
// To find the closest number to 'target', we use a variable to keep track and update when found a closer number.
27+
28+
public int threeSumClosest(int[] nums, int target) {
29+
// Sort the array, and use 2 variables to keep track of the minimum difference and the sum of the triplets.
30+
Arrays.sort(nums);
31+
32+
int minDiff = Integer.MAX_VALUE;
33+
int threeSum = 0;
34+
for (int i = 0; i < nums.length - 2; i++) {
35+
// If nums[i] is identical with the previous number skip the number to shorten the time.
36+
if (i > 0 && nums[i] == nums[i - 1]) continue;
37+
38+
// The following 'highSum' and 'lowSum' is additional check to shorten the time.
39+
// Otherwise, the rest of the code works on their own.
40+
//
41+
// The 'highSum' is to check if the largest possible sum for nums[i] is less than the target.
42+
// Since we have sorted the 'nums', we know all the remaining numbers will be smaller than the 'highSum'.
43+
// Thus, we can skip the remaining numbers if 'highSum' is lesser than target.
44+
int highSum = nums[i] + nums[nums.length - 1] + nums[nums.length - 2];
45+
if (highSum < target) {
46+
if (target - highSum < minDiff) {
47+
threeSum = highSum;
48+
minDiff = target - highSum;
49+
}
50+
continue;
51+
}
52+
// The 'lowSum' is to check if the smallest possible sum for nums[i] is greater than the target.
53+
// Since we have sorted the 'nums', we know all the remaining numbers will be greater than the 'lowSum'.
54+
// If the 'lowSum' is greater than the target,
55+
// the remaining numbers, including the subsequent i-th numbers will be greater than the 'lowSum'.
56+
// Thus, we are sure that 'lowSum' is the closest triplet to 'target', if found.
57+
int lowSum = nums[i] + nums[i + 1] + nums[i + 2];
58+
if (lowSum > target) {
59+
if (lowSum - target < minDiff) {
60+
return lowSum;
61+
}
62+
}
63+
64+
// After the initial checks, use two pointers, 'left' and 'right'.
65+
int left = i + 1;
66+
int right = nums.length - 1;
67+
while (left < right) {
68+
int sum = nums[left] + nums[right] + nums[i];
69+
int difference = Math.abs(sum - target);
70+
// If the triplet's 'minDiff' is lesser, then record it as the closest 'threeSum' for now.
71+
if (difference < minDiff) {
72+
minDiff = difference;
73+
threeSum = sum;
74+
}
75+
// Otherwise, decrease the 'right' if sum > target,
76+
if (sum > target) {
77+
right--;
78+
while (left < right && nums[right] == nums[right + 1]) right--;
79+
}
80+
// and increase 'left' if sum < target.
81+
else if (sum < target) {
82+
left++;
83+
while (left < right && nums[left] == nums[left - 1]) left++;
84+
}
85+
// If found sum == target, then it is the closest possible.
86+
else {
87+
return sum;
88+
}
89+
}
90+
}
91+
return threeSum;
92+
}
93+
}

0 commit comments

Comments
 (0)