One Trick to Solve All N-Sum Problems
This article will resolve
LeetCode | Difficulty |
---|---|
1. Two Sum | 🟢 |
15. 3Sum | 🟠 |
167. Two Sum II - Input Array Is Sorted | 🟠 |
18. 4Sum | 🟠 |
Prerequisite Knowledge
Before reading this article, you should first learn:
If you often practice problems on LeetCode, you must know the famous twoSum
problem. Besides twoSum
, LeetCode also has 3Sum
, 4Sum
, and maybe in the future even 5Sum
, 6Sum
.
To sum up, these nSum
problems ask you to find n
numbers from an array nums
whose sum is equal to a given target
.
Is there a good way to solve such problems with a pattern? In this article, I will explain step by step, and show how to use one function to solve all nSum
type problems.
1. The twoSum Problem
Let’s start with a twoSum problem:
Suppose you are given an array nums
and a target value target
. Please return two elements from nums
whose sum is equal to target
. For example, if nums = [1,3,5,6], target = 9
, the algorithm should return [3,6]
. You can assume there is only one pair that adds up to target
.
We can first sort nums
, then use the two pointer technique we learned before. Just use two pointers, one from each end, and move towards each other:
int[] twoSum(int[] nums, int target) {
// first sort the array
Arrays.sort(nums);
// left and right pointers
int lo = 0, hi = nums.length - 1;
while (lo < hi) {
int sum = nums[lo] + nums[hi];
// move the left and right pointers based on the comparison of sum and target
if (sum < target) {
lo++;
} else if (sum > target) {
hi--;
} else if (sum == target) {
return new int[]{nums[lo], nums[hi]};
}
}
return new int[]{};
}
std::vector<int> twoSum(std::vector<int>& nums, int target) {
// first sort the array
std::sort(nums.begin(), nums.end());
// left and right pointers
int lo = 0, hi = nums.size() - 1;
while (lo < hi) {
int sum = nums[lo] + nums[hi];
// move the left and right pointers based on the comparison of sum and target
if (sum < target) {
lo++;
} else if (sum > target) {
hi--;
} else if (sum == target) {
return {nums[lo], nums[hi]};
}
}
return {};
}
def twoSum(nums, target):
# first sort the array
nums.sort()
# left and right pointers
lo, hi = 0, len(nums) - 1
while lo < hi:
sum_nums = nums[lo] + nums[hi]
# move the left and right pointers based on the comparison of sum and target
if sum_nums < target:
lo += 1
elif sum_nums > target:
hi -= 1
elif sum_nums == target:
return [nums[lo], nums[hi]]
return []
func twoSum(nums []int, target int) []int {
// first sort the array
sort.Ints(nums)
// left and right pointers
lo, hi := 0, len(nums) - 1
for lo < hi {
sum := nums[lo] + nums[hi]
// move the left and right pointers based on the comparison of sum and target
if sum < target {
lo++
} else if sum > target {
hi--
} else if sum == target {
return []int{nums[lo], nums[hi]}
}
}
return []int{}
}
var twoSum = function(nums, target) {
// first sort the array
nums.sort(function(a, b) {return a - b});
// left and right pointers
var lo = 0, hi = nums.length - 1;
while (lo < hi) {
var sum = nums[lo] + nums[hi];
// move the left and right pointers based on the comparison of sum and target
if (sum < target) {
lo++;
} else if (sum > target) {
hi--;
} else if (sum == target) {
return [nums[lo], nums[hi]];
}
}
return [];
};
This solves the problem. LeetCode Problem 1 "Two Sum" and Problem 167 "Two Sum II - Input Array Is Sorted" can be solved in a similar way with some changes, so I won’t write them here.
But let’s make the problem a bit more general and harder:
Now, there may be multiple pairs in nums
whose sum is equal to target
. Please return all pairs whose sum is target
, and do not include duplicates.
Function signature is as follows:
List<List<Integer>> twoSumTarget(int[] nums, int target);
vector<vector<int>> twoSumTarget(vector<int>& nums, int target);
def twoSumTarget(nums: List[int], target: int) -> List[List[int]]:
func twoSumTarget(nums []int, target int) [][]int
var twoSumTarget = function(nums, target) {}
For example, if the input is nums = [1,3,1,2,2,3], target = 4
, the output should be: [[1,3],[2,2]]
(Note: I want the elements, not the indices).
For this new version, the key difficulty is that there may be many pairs that sum to target
, and you cannot have duplicates. For example, [1,3]
and [3,1]
are considered the same and should only be returned once.
First, the basic idea is still sorting and two pointers: