|
1 | 1 | # 3Sum and 4Sum
|
2 | 2 |
|
| 3 | +3Sum and 4Sum are extensions of a popular algorithm question, the [2Sum][5]. This article will talk about the problem and describe possible solutions. |
| 4 | + |
3 | 5 | ## 3Sum
|
4 |
| -Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? |
5 |
| -Find all unique triplets in the array which gives the sum of zero. |
6 | 6 |
|
7 |
| -**Note**: The solution set must not contain duplicate triplets. |
| 7 | +Given an array of integers, find all subsets of the array with 3 values where the 3 values sum up to a target number. |
8 | 8 |
|
9 |
| -> For example, given array S = [-1, 0, 1, 2, -1, -4], |
10 |
| -> A solution set is: [[-1, 0, 1], [-1, -1, 2]] |
| 9 | +**Note**: The solution subsets must not contain duplicate triplets. (Each element in the array can only be used once) |
11 | 10 |
|
12 |
| -### Solution |
13 |
| -Like [2Sum][5], we can sort the array first, then use 2 pointers method to solve the problem. But here, we need 3 numbers, so we need add one more pointer. But how to play with 3 pointers? |
| 11 | +> For example, given the array [-1, 0, 1, 2, -1, -4], and the target **0**: |
| 12 | +> The solution set is: [[-1, 0, 1], [-1, -1, 2]] // The two **-1** values in the array are considered to be distinct |
| 13 | +
|
| 14 | +### Example |
| 15 | + |
| 16 | +Consider the following array of integers, and a target sum of **0**: |
| 17 | + |
| 18 | +``` |
| 19 | +[-1, 0, 1, 2, -1, -4] |
| 20 | +``` |
| 21 | + |
| 22 | +#### 1. Sorting |
| 23 | + |
| 24 | +You'll first sort the array in ascending order: |
| 25 | + |
| 26 | +``` |
| 27 | +[-4, -1, -1, 0, 1, 2] |
| 28 | +``` |
| 29 | + |
| 30 | +#### 2. Two Sum's Methodology |
| 31 | + |
| 32 | +The 3Sum problem can be solved by augmenting the 2Sum solution, so let's begin by doing a quick explanation on how 2Sum handles the solution. 2Sum begins by comparing the left and right most values: |
| 33 | + |
| 34 | +``` |
| 35 | +[-4, -1, -1, 0, 1, 2] |
| 36 | + l r |
| 37 | +``` |
| 38 | + |
| 39 | +Your target sum is **0**. Given the current left and right values, you won't be able to make the target number. However, you've gained a valuable hint for your next step. |
| 40 | + |
| 41 | +``` |
| 42 | +-4 + 2 = -2 // too small! |
| 43 | +``` |
| 44 | + |
| 45 | +The result of `l + r` gave you a value that is smaller than the target number. Thus, you have two options: |
| 46 | + |
| 47 | +1. Increase the lower number. |
| 48 | +2. Increase the higher number. |
| 49 | + |
| 50 | +Because your array is sorted, you can quickly identify that you cannot pick option **2**, since the rightmost number is already the biggest number. Thus, you have no choice but to try for a different number from the left end of the array: |
| 51 | + |
| 52 | +``` |
| 53 | +[-4, -1, -1, 0, 1, 2] |
| 54 | + l r |
| 55 | +``` |
| 56 | + |
| 57 | +This time, you'll get the following result from summing `l` and `r`: |
| 58 | + |
| 59 | +``` |
| 60 | +-1 + 2 = 1 // too big! |
| 61 | +``` |
| 62 | + |
| 63 | +This time, the value is too big! I hope you see where it goes from here. Since the array is already sorted, you can only decrease the value on the right side in an attempt to balance things out. Hence, the next iteration of your algorithm will look like this: |
| 64 | + |
| 65 | +``` |
| 66 | +[-4, -1, -1, 0, 1, 2] |
| 67 | + l r |
| 68 | +``` |
| 69 | + |
| 70 | +And then you've found a match :] |
| 71 | + |
| 72 | +``` |
| 73 | +-1 + 1 = 0 |
| 74 | +``` |
| 75 | + |
| 76 | +#### Augmenting 2Sum |
| 77 | + |
| 78 | +Let's start from scratch and consider the same problem where you've sorted your input and you're target sum is **0**: |
| 79 | + |
| 80 | +``` |
| 81 | +[-4, -1, -1, 0, 1, 2] |
| 82 | + l r |
| 83 | +``` |
| 84 | + |
| 85 | +Your goal this time is the following equation: |
| 86 | + |
| 87 | +``` |
| 88 | +l + r + m = 0 |
| 89 | +``` |
| 90 | + |
| 91 | +You have the values of `l` and `r`: |
| 92 | + |
| 93 | +``` |
| 94 | +-4 + 2 + m = 0 |
| 95 | +
|
| 96 | +// in other words |
| 97 | +m = 4 - 2 = 2 |
| 98 | +``` |
| 99 | + |
| 100 | +For the current values of `l` and `r`, you need to find a value of **2** in the array to satisfy your target sum... |
| 101 | + |
| 102 | +#### Finding `m` |
| 103 | + |
| 104 | +``` |
| 105 | + m -- where? |
| 106 | +[-4, -1, -1, 0, 1, 2] |
| 107 | + l r |
| 108 | +``` |
| 109 | + |
| 110 | +There are slight optimizations you can do to find `m`, but to keep things simple, you'll just iterate through the array from `l` index to the `r` index. Once you find a value where `l + r + m = target`, you've found your first match! |
| 111 | + |
| 112 | +#### Avoiding Duplicates |
| 113 | + |
| 114 | +// TODO: Work in progress |
14 | 115 |
|
15 |
| -The key idea here is we split the array into 2 parts, if we have a pointer `i`, let’s assume we got `i` position already. What’ next? Actually, next is just a 2Sum problem right? We can just apply 2 pointers method in 2Sum. But what’s 2Sum’s target sum? Is it `target2Sum = target3Sum - nums[i]` ? That’s awesome! |
| 116 | +Avoiding duplicate values is fairly straightforward if you've understood everything so far. Let's consider a sample array that has a few duplicates: |
16 | 117 |
|
17 |
| -How we figure out `i`? We can loop i from `0` to `nums.count - 1`. |
| 118 | +``` |
| 119 | +target = 0 |
18 | 120 |
|
19 |
| -How we avoid duplicate triplets? Since the array has been sorted, we just need to check if `a[i] == a[i-1]`. Why? Because if `a[i] == a[i-1]`, it means that `a[i-1]` already covers all `a[i]` solutions, we should not do it, otherwise it will have duplicate answers. The same for `j` and `k` which runs for 2Sum. |
| 121 | +[-1, -1, -1, -1, 0, 1, 1, 1] |
| 122 | +``` |
20 | 123 |
|
21 |
| -So, we successfully downgrade 3Sum to 2Sum problem with some tricks. Next, you will see how we downgrade 4Sum to 3Sum. |
| 124 | +One possible subset is `[-1, 0, 1]`, and in fact is the only subset for 3Sum. |
22 | 125 |
|
23 | 126 | ## 4Sum
|
24 | 127 | Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
|
|
0 commit comments