@@ -29,19 +29,15 @@ Since you pre-sort the array, duplicates will be adjacent to each other. You jus
29
29
```
30
30
extension Collection where Element: Equatable {
31
31
32
- /// Returns next index with unique value. Works only on sorted arrays .
32
+ /// In a sorted collection, replaces the given index with a successor mapping to a unique element .
33
33
///
34
- /// - Parameter index: The current index.
35
- /// - Returns: The new index. Will return `nil` if new index happens to be the `endIndex` (out of bounds)
36
- func uniqueIndex(after index: Index) -> Index? {
37
- guard index < endIndex else { return nil }
38
- var index = index
39
- var nextIndex = self.index(after: index)
40
- while nextIndex < endIndex && self[index] == self[nextIndex] {
34
+ /// - Parameter index: A valid index of the collection. `index` must be less than `endIndex`
35
+ func formUniqueIndex(after index: inout Index) {
36
+ var prev = index
37
+ repeat {
38
+ prev = index
41
39
formIndex(after: &index)
42
- formIndex(after: &nextIndex)
43
- }
44
- return nextIndex != endIndex ? nextIndex : nil
40
+ } while index < endIndex && self[prev] == self[index]
45
41
}
46
42
}
47
43
```
@@ -51,16 +47,15 @@ A similar implementation is used to get the unique index *before* a given index:
51
47
```
52
48
extension BidirectionalCollection where Element: Equatable {
53
49
54
- /// Returns next index with unique value. Works only on sorted arrays .
50
+ /// In a sorted collection, replaces the given index with a predecessor that maps to a unique element .
55
51
///
56
- /// - Parameter index: The current index.
57
- /// - Returns: The new index. Will return `nil` if new index happens to come before the `startIndex` (out of bounds)
58
- func uniqueIndex(before index: Index) -> Index? {
59
- return indices[..<index].reversed().first { index -> Bool in
60
- let nextIndex = self.index(after: index)
61
- guard nextIndex >= startIndex && self[index] != self[nextIndex] else { return false }
62
- return true
63
- }
52
+ /// - Parameter index: A valid index of the collection. `index` must be greater than `startIndex`.
53
+ func formUniqueIndex(before index: inout Index) {
54
+ var prev = index
55
+ repeat {
56
+ prev = index
57
+ formIndex(before: &index)
58
+ } while index > startIndex && self[prev] == self[index]
64
59
}
65
60
}
66
61
```
@@ -78,40 +73,36 @@ You'll keep track of 3 indices to represent the 3 numbers. The sum at any given
78
73
The premise is quite straightforward (given that you're familiar with 2Sum). You'll iterate ` l ` through the array. For every iteration, you also apply the 2Sum algorithm to elements after ` l ` . You'll check the sum every time you moving the indices to check if you found match. Here's the algorithm:
79
74
80
75
```
81
- func threeSum<T: BidirectionalCollection>(_ c : T, target: T.Element) -> [[T.Element]] where T.Element: Numeric & Comparable {
82
- let sorted = c .sorted()
76
+ func threeSum<T: BidirectionalCollection>(_ collection : T, target: T.Element) -> [[T.Element]] where T.Element: Numeric & Comparable {
77
+ let sorted = collection .sorted()
83
78
var ret: [[T.Element]] = []
79
+ var l = sorted.startIndex
84
80
85
- for l in sequence(first: sorted.startIndex, next: sorted.uniqueIndex(after:)) {
81
+ while l < sorted.endIndex {
86
82
var m = sorted.index(after: l)
87
83
var r = sorted.index(before: sorted.endIndex)
88
84
89
- while m < r {
85
+ while m < r && r < sorted.endIndex {
90
86
let sum = sorted[l] + sorted[m] + sorted[r]
91
- switch sum {
92
- case target :
87
+ switch target {
88
+ case sum :
93
89
ret.append([sorted[l], sorted[m], sorted[r]])
94
- guard let nextM = sorted.uniqueIndex(after: m), let nextR = sorted.uniqueIndex(before: r) else { break }
95
- m = nextM
96
- r = nextR
90
+ sorted.formUniqueIndex(after: &m)
91
+ sorted.formUniqueIndex(before: &r)
97
92
case ..<target:
98
- guard let nextM = sorted.uniqueIndex(after: m) else { break }
99
- m = nextM
93
+ sorted.formUniqueIndex(after: &m)
100
94
case target...:
101
- guard let nextR = sorted.uniqueIndex(before: m) else { break }
102
- r = nextR
103
- default: fatalError()
95
+ sorted.formUniqueIndex(before: &r)
96
+ default: fatalError("Swift isn't smart enough to detect that this switch statement is exhausive")
104
97
}
105
98
}
99
+ sorted.formUniqueIndex(after: &l)
106
100
}
107
101
108
102
return ret
109
103
}
110
104
```
111
105
112
-
113
-
114
-
115
106
## 4Sum
116
107
Given an array S of n integers, find all subsets of the array with 4 values where the 4 values sum up to a target number.
117
108
0 commit comments