|
1 | 1 | # Two-Sum Problem
|
2 | 2 |
|
3 |
| -You're given an array of numbers. Write an algorithm that checks if there are any two elements in the array that add up to a given number. |
| 3 | +Given an array of integers and an integer target, return the indices of two numbers that add up to the target. |
4 | 4 |
|
5 | 5 | There are a variety of solutions to this problem (some better than others). The following solutions both run in **O(n)** time.
|
6 | 6 |
|
7 | 7 | # Solution 1
|
8 | 8 |
|
9 |
| -This solution uses a dictionary to store differences between each element in the array and the sum that we're looking for. The dictionary also stores the indices of each element. |
| 9 | +This solution looks at one number at a time, storing each number in the dictionary. It uses the number as the key and the number's index in the array as the value. |
10 | 10 |
|
11 |
| -With this approach, each key in the dictionary corresponds to a new target value. If one of the successive numbers from the array is equal to one of the dictionary's keys, then we know there exist two numbers that sum. |
| 11 | +For each number n, we know the complementing number to sum up to the target is `target - n`. By looking up the complement in the dictionary, we'd know whether we've seen the complement before and what its index is. |
12 | 12 |
|
13 | 13 | ```swift
|
14 |
| -func twoSumProblem(_ numbers: [Int], target: Int) -> (Int, Int)? { |
15 |
| - var dict: [Int: Int] = [:] |
16 |
| - |
17 |
| - for (index, number) in numbers.enumerated() { |
18 |
| - if let otherIndex = dict[number] { |
19 |
| - return (index, otherIndex) |
20 |
| - } else { |
21 |
| - dict[target - number] = index |
| 14 | +func twoSum(_ nums: [Int], target: Int) -> (Int, Int)? { |
| 15 | + var dict = [Int: Int]() |
| 16 | + |
| 17 | + // For every number n, |
| 18 | + for (currentIndex, n) in nums.enumerated() { |
| 19 | + // Find the complement to n that would sum up to the target. |
| 20 | + let complement = target - n |
| 21 | + |
| 22 | + // Check if the complement is in the dictionary. |
| 23 | + if let complementIndex = dict[complement] { |
| 24 | + return (complementIndex, currentIndex) |
| 25 | + } |
| 26 | + |
| 27 | + // Store n and its index into the dictionary. |
| 28 | + dict[n] = currentIndex |
22 | 29 | }
|
23 |
| - } |
24 |
| - |
25 |
| - return nil // if empty array or no entries sum to target k |
| 30 | + |
| 31 | + return nil |
26 | 32 | }
|
27 | 33 | ```
|
28 | 34 |
|
29 |
| -The `twoSumProble` function takes two parameters: the `numbers` array and the target sum you're looking for. It returns the 2 indices with elements that sums up to the target, or `nil` if it can't be found. |
| 35 | +The `twoSum` function takes two parameters: the `numbers` array and the target sum. It returns the two indicies of the pair of elements that sums up to the target, or `nil` if they can't be found. |
30 | 36 |
|
31 |
| -Let's take a look at an example and run through the algorithm to see how it works. Given is the array: |
| 37 | +Let's run through the algorithm to see how it works. Given the array: |
32 | 38 |
|
33 | 39 | ```swift
|
34 |
| -[ 7, 2, 23, 8, -1, 0, 11, 6 ] |
| 40 | +[3, 2, 9, 8] |
35 | 41 | ```
|
36 | 42 |
|
37 |
| -Let's find out if there exist two entries whose sum is equal to 10. |
| 43 | +Let's find out if there exist two entries whose sum is 10. |
38 | 44 |
|
39 | 45 | Initially, our dictionary is empty. We begin looping through each element:
|
40 | 46 |
|
41 |
| -- **i = 0**: Is `7` in the dictionary? No. We add the difference between the `target` and the current number to the dictionary. The difference is `10 - 7 = 3`, so the dictionary key is `3`. The value for that key is the current index, `0`. The dictionary now looks like this: |
| 47 | +- **currentIndex = 0** | n = nums[0] = 3 | complement = 10 - 3 = 7 |
| 48 | + |
| 49 | +Is the complement `7` in the dictionary? No, so we add `3` and its index `0` to the dictionary. |
42 | 50 |
|
43 | 51 | ```swift
|
44 |
| -[ 3: 0 ] |
| 52 | +[3: 0] |
45 | 53 | ```
|
46 | 54 |
|
47 |
| -- **i = 1:** Is `2` in the dictionary? No. Let's do as above and add the difference (`10 - 2 = 8`) and the array index (`1`). The dictionary is: |
| 55 | +- **currentIndex = 1** | n = 2 | complement = 10 - 2 = 8 |
| 56 | + |
| 57 | +Is the complement `8` in the dictionary? No, so we add `2` and its index `1` to the dictionary. |
48 | 58 |
|
49 | 59 | ```swift
|
50 |
| -[ 3: 0, 8: 1 ] |
| 60 | +[3: 0, 2: 1] |
51 | 61 | ```
|
52 | 62 |
|
53 |
| -- **i = 2:** Is `23` in the dictionary? No. Again, we add it to the dictionary. The difference is `10 - 23 = -13` and the index is `2`: |
| 63 | +- **currentIndex = 2** | n = 9 | complement = 10 - 9 = 1 |
| 64 | + |
| 65 | +Is the complement `1` in the dictionary? No, so we add `9` and its index `2` to the dictionary.: |
54 | 66 |
|
55 | 67 | ```swift
|
56 |
| -[ 3: 0, 8: 1, -13: 2 ] |
| 68 | +[3: 0, 2: 1, 9: 2] |
57 | 69 | ```
|
58 | 70 |
|
59 |
| -- **i = 3:** Is `8` in the dictionary? Yes! That means that we have found a pair of entries that sum to our target. Namely the current number `8` and `array[dict[8]]` because `dict[8] = 1`, `array[1] = 2`, and `8 + 2 = 10`. Therefore, we return the corresponding indices of these numbers. For `8` that is the current loop index, `3`. For `2` that is `dict[8]` or `1`. The tuple we return is `(1, 3)`. |
| 71 | +- **currentIndex = 3** | n = 8 | complement = 10 - 8 = 2 |
| 72 | + |
| 73 | +Is the complement `2` in the dictionary? Yes! That means that we have found a pair of entries that sum to the target! |
| 74 | + |
| 75 | +Therefore, the `complementIndex = dict[2] = 1` and the `currentIndex = 3`. The tuple we return is `(1, 3)`. |
60 | 76 |
|
61 |
| -The given array actually has multiple solutions: `(1, 3)` and `(4, 6)`. However, only the first solution is returned. |
| 77 | +If the given array has multiple solutions, only the first solution is returned. |
62 | 78 |
|
63 |
| -The running time of this algorithm is **O(n)** because it potentially may need to look at all array elements. It also requires **O(n)** additional storage space for the dictionary. |
| 79 | +The running time of this algorithm is **O(n)** because it may look at every element in the array. It also requires **O(n)** additional storage space for the dictionary. |
64 | 80 |
|
65 | 81 | # Solution 2
|
66 | 82 |
|
|
0 commit comments