Skip to content

Commit 2e9818e

Browse files
author
Chris Pilcher
committed
Merge branch 'master' of https://github.com/hollance/swift-algorithm-club into Select-Minimum-Maximum
2 parents 6a264af + ee9a695 commit 2e9818e

File tree

10 files changed

+134
-31
lines changed

10 files changed

+134
-31
lines changed

Two-Sum Problem/2Sum.playground/Contents.swift

Lines changed: 0 additions & 29 deletions
This file was deleted.

Two-Sum Problem/README.markdown

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,53 @@
22

33
You're given an array `a` with numbers. Write an algorithm that checks if there are any two entries in the array that add up to a given number `k`. In other words, is there any `a[i] + a[j] == k`?
44

5-
There are a variety of solutions to this problem (some better than others) but I quite like the following.
5+
There are a variety of solutions to this problem (some better than others). The following solutions both run in O(n) time.
6+
7+
# Solution 1
8+
9+
This solution uses a dictionary to store differences between the target value and each element, along with the corresponding indices. With this approach, each key found in the dictionary corresponds with a new target value; if any new target value is found (i.e. one of the following entries is equal to one of the dictionary's keys), then we know there exists two entries that sum to the given k, namely the current entry, and the entry i (the value stored in the dictionary whose k equals the current entry).
10+
11+
**Note:** This solution returns the first set of indices `(i, j)` where `a[i] + a[j] == k`.
12+
13+
```swift
14+
func twoSumProblem(a: [Int], k: Int) -> ((Int, Int))? {
15+
var dict = [Int: Int]()
16+
17+
for i in 0 ... a.count - 1 {
18+
if let newK = dict[a[i]] {
19+
return (newK, i)
20+
} else {
21+
dict[k - a[i]] = i
22+
}
23+
}
24+
25+
return nil // if empty array or no entries sum to target k
26+
}
27+
```
28+
29+
Let's take a look at an example and run through the algorithm to see how it works:
30+
Given an array: {8, 1, 23, 9, -1, 0, 11, 6}
31+
Let's find out if there exist two entries whose sum is equal to 10.
32+
33+
Initially, our dictionary is empty. We begin looping through each element:
34+
i = 0:
35+
Is `8` in the dictionary? No. Let's add the difference between the target and the current element, and the current index to the dictionary: {10 - 8 => 0} = {2 => 0}
36+
dict = {2 => 0}
37+
38+
i = 1:
39+
Is `1` in the dictionary? No. Let's do as above and add it: `{10 - 1 => 1} = {9 => 1}`
40+
`dict = {2 => 0, 9 => 1}`
41+
42+
i = 2:
43+
Is `23` in the dictionary? No. Let's do as above and add it: `{10 - 23 => 2} = {-13 => 2}`
44+
`dict = {2 => 0, 9 => 1, -13 => 2}`
45+
46+
i = 3:
47+
Is `9` in the dictionary? Yes! That means that we have found a pair of entries that sum to our target. Namely `9` and `array[dict[9]]`. `9 + array[dict[9]] = 9 + array[1] = 9 + 1 = 10`. Therefore, we return the corresponding indices of the entries `1` and `9`: `(1, 3)`.
48+
49+
**Note:** This array has multiple solutions: `(1, 3), and (4, 6)`, however only the first solution is returned.
50+
51+
# Solution 2
652

753
**Note**: This particular algorithm requires that the array is sorted, so if the array isn't sorted yet (usually it won't be), you need to sort it first. The time complexity of the algorithm itself is **O(n)** but if you have to sort first, the total time complexity becomes **O(n log n)**. Slightly worse but still quite acceptable.
854

@@ -88,4 +134,4 @@ It's possible, of course, that there are no values for `a[i] + a[j]` that sum to
88134

89135
I'm quite enamored by this little algorithm. It shows that with some basic preprocessing on the input data -- sorting it from low to high -- you can turn a tricky problem into a very simple and beautiful algorithm.
90136

91-
*Written by Matthijs Hollemans*
137+
*Written by Matthijs Hollemans and Daniel Speiser*
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//: Playground - noun: a place where people can play
2+
3+
func twoSumProblem(a: [Int], k: Int) -> ((Int, Int))? {
4+
var map = [Int: Int]()
5+
6+
for i in 0 ... a.count - 1 {
7+
if let newK = map[a[i]] {
8+
return (newK, i)
9+
} else {
10+
map[k - a[i]] = i
11+
}
12+
}
13+
return nil
14+
}
15+
16+
let a = [7, 100, 2, 21, 12, 10, 22, 14, 3, 4, 8, 4, 9]
17+
if let (i, j) = twoSumProblem(a, k: 33) {
18+
i // 3
19+
a[i] // 21
20+
j // 4
21+
a[j] // 12
22+
a[i] + a[j] // 33
23+
}
24+
25+
twoSumProblem(a, k: 37) // nil

Two-Sum Problem/solution_1/2Sum.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
Determines if there are any entries a[i] + a[j] == k in the array.
3+
Returns the indices of the first pair of elements that sum to k as a tuple.
4+
5+
Uses a dictionary to store differences between the target and each element.
6+
If any value in the dictionary equals an element in the array, they sum to k.
7+
8+
This is an O(n) solution.
9+
*/
10+
func twoSumProblem(a: [Int], k: Int) -> ((Int, Int))? {
11+
var map = [Int: Int]()
12+
13+
for i in 0 ... a.count - 1 {
14+
if let newK = map[a[i]] {
15+
return (newK, i)
16+
} else {
17+
map[k - a[i]] = i
18+
}
19+
}
20+
21+
return nil // if empty array or no entries sum to target k
22+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//: Playground - noun: a place where people can play
2+
3+
func twoSumProblem(a: [Int], k: Int) -> ((Int, Int))? {
4+
var i = 0
5+
var j = a.count - 1
6+
7+
while i < j {
8+
let sum = a[i] + a[j]
9+
if sum == k {
10+
return (i, j)
11+
} else if sum < k {
12+
++i
13+
} else {
14+
--j
15+
}
16+
}
17+
return nil
18+
}
19+
20+
let a = [2, 3, 4, 4, 7, 8, 9, 10, 12, 14, 21, 22, 100]
21+
if let (i, j) = twoSumProblem(a, k: 33) {
22+
i // 8
23+
a[i] // 12
24+
j // 10
25+
a[j] // 21
26+
a[i] + a[j] // 33
27+
}
28+
29+
twoSumProblem(a, k: 37) // nil
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='osx'>
3+
<timeline fileName='timeline.xctimeline'/>
4+
</playground>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Timeline
3+
version = "3.0">
4+
<TimelineItems>
5+
</TimelineItems>
6+
</Timeline>
File renamed without changes.

0 commit comments

Comments
 (0)