From 982a6c214cbb6b844e4dc5d3ce9ce2788d2aaa78 Mon Sep 17 00:00:00 2001 From: Chee Hwa Tang Date: Fri, 1 Sep 2023 22:28:12 +0800 Subject: [PATCH 1/2] 16. 3Sum Closest --- .../16. 3Sum Closest/ThreeSumClosest.java | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 solutions/16. 3Sum Closest/ThreeSumClosest.java diff --git a/solutions/16. 3Sum Closest/ThreeSumClosest.java b/solutions/16. 3Sum Closest/ThreeSumClosest.java new file mode 100644 index 0000000..671e283 --- /dev/null +++ b/solutions/16. 3Sum Closest/ThreeSumClosest.java @@ -0,0 +1,93 @@ +package com.cheehwatang.leetcode; + +import java.util.Arrays; + +// Time Complexity : O(n^2), +// where 'n' is the length of 'nums'. +// We traverse 'nums' to check each 'nums[i]', with each element we use 2 pointers, +// thus it is a nested loop, with O(n^2) time complexity. +// The Arrays.sort() function has a time complexity of O(n logn). +// +// Space Complexity : O(1), +// as the auxiliary space used is independent of the input. + +public class ThreeSumClosest { + + // Approach: + // Use sorting and two pointers to search for all the triplets and check for the closest sum to 'target'. + // For each 'nums[i]' in 'nums', we can check the sum with nums[j] and nums[k] using two pointers, + // 'left' and 'right' to traverse the remaining numbers. + // In order to use two pointers in this manner, we have to first sort the array in ascending order. + // This allows use to check if nums[i] + nums[j] + nums[k] is greater or less than 0. + // If the sum is less than 'target', then we shift the 'left' pointer to the right. + // If the sum is greater than 'target', then we shift the 'right' pointer to the left. + // If we found the sum to be equal to 'target', then we return 'target'. + // + // To find the closest number to 'target', we use a variable to keep track and update when found a closer number. + + public int threeSumClosest(int[] nums, int target) { + // Sort the array, and use 2 variables to keep track of the minimum difference and the sum of the triplets. + Arrays.sort(nums); + + int minDiff = Integer.MAX_VALUE; + int threeSum = 0; + for (int i = 0; i < nums.length - 2; i++) { + // If nums[i] is identical with the previous number skip the number to shorten the time. + if (i > 0 && nums[i] == nums[i - 1]) continue; + + // The following 'highSum' and 'lowSum' is additional check to shorten the time. + // Otherwise, the rest of the code works on their own. + // + // The 'highSum' is to check if the largest possible sum for nums[i] is less than the target. + // Since we have sorted the 'nums', we know all the remaining numbers will be smaller than the 'highSum'. + // Thus, we can skip the remaining numbers if 'highSum' is lesser than target. + int highSum = nums[i] + nums[nums.length - 1] + nums[nums.length - 2]; + if (highSum < target) { + if (target - highSum < minDiff) { + threeSum = highSum; + minDiff = target - highSum; + } + continue; + } + // The 'lowSum' is to check if the smallest possible sum for nums[i] is greater than the target. + // Since we have sorted the 'nums', we know all the remaining numbers will be greater than the 'lowSum'. + // If the 'lowSum' is greater than the target, + // the remaining numbers, including the subsequent i-th numbers will be greater than the 'lowSum'. + // Thus, we are sure that 'lowSum' is the closest triplet to 'target', if found. + int lowSum = nums[i] + nums[i + 1] + nums[i + 2]; + if (lowSum > target) { + if (lowSum - target < minDiff) { + return lowSum; + } + } + + // After the initial checks, use two pointers, 'left' and 'right'. + int left = i + 1; + int right = nums.length - 1; + while (left < right) { + int sum = nums[left] + nums[right] + nums[i]; + int difference = Math.abs(sum - target); + // If the triplet's 'minDiff' is lesser, then record it as the closest 'threeSum' for now. + if (difference < minDiff) { + minDiff = difference; + threeSum = sum; + } + // Otherwise, decrease the 'right' if sum > target, + if (sum > target) { + right--; + while (left < right && nums[right] == nums[right + 1]) right--; + } + // and increase 'left' if sum < target. + else if (sum < target) { + left++; + while (left < right && nums[left] == nums[left - 1]) left++; + } + // If found sum == target, then it is the closest possible. + else { + return sum; + } + } + } + return threeSum; + } +} From 5e78d83ced60ae1ee680f796184add019b2bab4d Mon Sep 17 00:00:00 2001 From: Chee Hwa Tang Date: Fri, 1 Sep 2023 22:31:42 +0800 Subject: [PATCH 2/2] Added 16. 3Sum Closest --- README.md | 67 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 55 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 8115b80..83c3c50 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,19 @@ Solution Topics + + September 1st + 16. 3Sum Closest + $\text{\color{Dandelion}Medium}$ + + Sorting & Two Pointers + + + Array, + Sorting, + Two Pointers + + August 31st 15. 3Sum @@ -76,18 +89,6 @@ String - - August 27th - 3. Longest Substring Without Repeating Characters - $\text{\color{Dandelion}Medium}$ - - Sliding Window - - - Sliding Window, - String - -

@@ -178,6 +179,20 @@ + + 16 + 3Sum Closest + + Java + + $\text{\color{Dandelion}Medium}$ + + Array, + Sorting, + Two Pointers + + + 26 Remove Duplicates from Sorted Array @@ -7286,6 +7301,20 @@ + + 16 + 3Sum Closest + + Java + + $\text{\color{Dandelion}Medium}$ + + Array, + Sorting, + Two Pointers + + + 49 Group Anagrams @@ -9189,6 +9218,20 @@ + + 16 + 3Sum Closest + + Java + + $\text{\color{Dandelion}Medium}$ + + Array, + Sorting, + Two Pointers + + + 19 Remove Nth Node From End of List