Skip to content

Commit a792197

Browse files
committed
3Sum and 4Sum
Follow up 2Sum problem. How to solve 3Sum and 4Sum problem? What’s their relationships? Could we get some generic idea to solve this kind of problems? I give the explanation here.
1 parent d32c5e7 commit a792197

File tree

6 files changed

+179
-0
lines changed

6 files changed

+179
-0
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
func ThreeSum(_ nums: [Int], targetSum: Int) -> [[Int]] {
2+
var a = nums.sorted()
3+
var ret: [[Int]] = []
4+
5+
for i in 0..<a.count {
6+
if i != 0 && a[i] == a[i-1] {
7+
continue
8+
}
9+
10+
var j = i + 1
11+
var k = nums.count - 1
12+
13+
while j < k {
14+
let sum = a[i] + a[j] + a[k]
15+
16+
if sum == targetSum {
17+
ret.append([a[i], a[j], a[k]])
18+
j += 1
19+
} else if sum < targetSum {
20+
j += 1
21+
} else {
22+
k -= 1
23+
}
24+
25+
if sum == targetSum {
26+
while j < k {
27+
var flag = false
28+
if j != 0 && a[j] == a[j-1] {
29+
j += 1
30+
flag = true
31+
}
32+
33+
if (k != a.count - 1) && a[k] == a[k+1] {
34+
k -= 1
35+
flag = true
36+
}
37+
38+
if (!flag) {
39+
break
40+
}
41+
}
42+
}
43+
}
44+
}
45+
46+
return ret
47+
}
48+
49+
// Answer: [[-1, 0, 1], [-1, -1, 2]]
50+
ThreeSum([-1, 0, 1, 2, -1, -4], targetSum: 0)
51+
52+
// Answer: [[-1, -1, 1]]
53+
ThreeSum([-1, 1, 1, -1], targetSum: 1)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<playground version='5.0' target-platform='ios'>
3+
<timeline fileName='timeline.xctimeline'/>
4+
</playground>
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
func FourSum(_ nums: [Int], target: Int) -> [[Int]] {
2+
let a = nums.sorted()
3+
var ret: [[Int]] = []
4+
5+
for i in 0..<nums.count {
6+
if i != 0 && a[i] == a[i-1] {
7+
continue
8+
}
9+
for j in i+1..<nums.count {
10+
if j != i+1 && a[j] == a[j-1] {
11+
continue
12+
}
13+
14+
var k = j + 1
15+
var t = nums.count - 1
16+
17+
while k < t {
18+
let sum = a[i] + a[j] + a[k] + a[t]
19+
20+
if sum == target {
21+
ret.append([a[i], a[j], a[k], a[t]])
22+
k += 1
23+
} else if sum < target {
24+
k += 1
25+
} else {
26+
t -= 1
27+
}
28+
29+
if sum == target {
30+
while k < t {
31+
var flag = true
32+
if k != j + 1 && a[k] == a[k-1] {
33+
k += 1
34+
flag = false
35+
}
36+
37+
if t != nums.count - 1 && a[t] == a[t+1] {
38+
t -= 1
39+
flag = false
40+
}
41+
42+
if flag {
43+
break
44+
}
45+
}
46+
}
47+
}
48+
}
49+
}
50+
51+
return ret
52+
}
53+
54+
/* Answer
55+
[
56+
[-1, 0, 0, 1],
57+
[-2, -1, 1, 2],
58+
[-2, 0, 0, 2]
59+
]
60+
*/
61+
FourSum([1, 0, -1, 0, -2, 2], target: 0)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<playground version='5.0' target-platform='ios'>
3+
<timeline fileName='timeline.xctimeline'/>
4+
</playground>

3Sum and 4Sum/README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# 3Sum and 4Sum
2+
3+
## 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+
7+
**Note**: The solution set must not contain duplicate triplets.
8+
9+
> For example, given array S = [-1, 0, 1, 2, -1, -4](),
10+
> A solution set is:
11+
> [
12+
> ]()> [-1, 0, 1](),
13+
> [-1, -1, 2]()
14+
> ]
15+
16+
### Solution
17+
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?
18+
19+
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!
20+
21+
How we figure out `i`? We can loop i from `0` to `nums.count - 1`.
22+
23+
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.
24+
25+
So, we successfully downgrade 3Sum to 2Sum problem with some tricks. Next, you will see how we downgrade 4Sum to 3Sum.
26+
27+
## 4Sum
28+
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.
29+
30+
**Note**: The solution set must not contain duplicate quadruplets.
31+
32+
### Solution
33+
After 3Sum, you should have feeling actually we just need a same idea to downgrade it to 3Sum, and then 2Sum, and then solve it.
34+
35+
How? I will leave it as a challenge for you to figure out first and see if you really master the idea behind this kind of problems.
36+
37+
Feel free to check out the solution if you are blocked.
38+
39+
## Where to go next?
40+
If it’s a KSum, and `K` is a big number, do we need to create `K` pointers and solve it?
41+
42+
I will write another topic to present how we will solve this KSum problem with a generic way soon.
43+
44+
45+
46+
47+
48+
[5]: https://github.com/raywenderlich/swift-algorithm-club/tree/master/Two-Sum%20Problem

swift-algorithm-club.xcworkspace/contents.xcworkspacedata

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)