Skip to content

Commit 1279b37

Browse files
authored
Updates implementation.
1 parent 1fc26da commit 1279b37

File tree

1 file changed

+67
-50
lines changed

1 file changed

+67
-50
lines changed
Lines changed: 67 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,76 @@
1-
func ThreeSum(_ nums: [Int], targetSum: Int) -> [[Int]] {
2-
var a = nums.sorted()
3-
var ret: [[Int]] = []
4-
5-
for m in 0..<a.count {
6-
if m != 0 && a[m] == a[m-1] {
7-
continue
8-
}
9-
10-
var l = m + 1
11-
var r = nums.count - 1
12-
13-
while l < r {
14-
let sum = a[m] + a[l] + a[r]
15-
16-
if sum == targetSum {
17-
ret.append([a[m], a[l], a[r]])
18-
l += 1
19-
} else if sum < targetSum {
20-
l += 1
21-
} else {
22-
r -= 1
23-
}
24-
25-
if sum == targetSum {
26-
while l < r {
27-
var flag = false
28-
if l != 0 && a[l] == a[l-1] {
29-
l += 1
30-
flag = true
31-
}
32-
33-
if (r != a.count - 1) && a[r] == a[r+1] {
34-
r -= 1
35-
flag = true
36-
}
37-
38-
if (!flag) {
39-
break
40-
}
41-
}
42-
}
43-
}
1+
extension Collection where Element: Equatable {
2+
3+
/// Returns next index with unique value. Works only on sorted arrays.
4+
///
5+
/// - Parameter index: The current `Int` index.
6+
/// - Returns: The new `Int` index. Will return `nil` if new index happens to be the `endIndex` (out of bounds)
7+
func uniqueIndex(after index: Index) -> Index? {
8+
guard index < endIndex else { return nil }
9+
var index = index
10+
var nextIndex = self.index(after: index)
11+
while nextIndex < endIndex && self[index] == self[nextIndex] {
12+
formIndex(after: &index)
13+
formIndex(after: &nextIndex)
4414
}
4515

46-
return ret
16+
if nextIndex == endIndex {
17+
return nil
18+
} else {
19+
return nextIndex
20+
}
21+
}
4722
}
4823

49-
// Answer: [[-1, 0, 1], [-1, -1, 2]]
50-
ThreeSum([-1, 0, 1, 2, -1, -4], targetSum: 0)
24+
extension BidirectionalCollection where Element: Equatable {
25+
26+
/// Returns next index with unique value. Works only on sorted arrays.
27+
///
28+
/// - Parameter index: The current `Int` index.
29+
/// - Returns: The new `Int` index. Will return `nil` if new index happens to come before the `startIndex` (out of bounds)
30+
func uniqueIndex(before index: Index) -> Index? {
31+
return indices[..<index].reversed().first { index -> Bool in
32+
let nextIndex = self.index(after: index)
33+
guard nextIndex >= startIndex && self[index] != self[nextIndex] else { return false }
34+
return true
35+
}
36+
}
37+
}
5138

52-
// Answer: [[-1, -1, 1]]
53-
ThreeSum([-1, 1, 1, -1], targetSum: 1)
39+
func threeSum<T: BidirectionalCollection>(_ collection: T, target: T.Element) -> [[T.Element]] where T.Element: BinaryInteger & Comparable {
40+
let sorted = collection.sorted()
41+
var ret: [[T.Element]] = []
42+
43+
for l in sequence(first: sorted.startIndex, next: sorted.uniqueIndex(after:)) {
44+
var m = sorted.index(after: l)
45+
var r = sorted.index(before: sorted.endIndex)
46+
47+
while m < r {
48+
let sum = sorted[l] + sorted[m] + sorted[r]
49+
switch target {
50+
case sum:
51+
ret.append([sorted[l], sorted[m], sorted[r]])
52+
guard let nextMid = sorted.uniqueIndex(after: m), let nextRight = sorted.uniqueIndex(before: r) else { break }
53+
m = nextMid
54+
r = nextRight
55+
case ..<target:
56+
guard let nextMid = sorted.uniqueIndex(after: m) else { break }
57+
m = nextMid
58+
case target...:
59+
guard let nextRight = sorted.uniqueIndex(before: r) else { break }
60+
r = nextRight
61+
default: fatalError("Swift isn't smart enough to detect that this switch statement is exhausive")
62+
}
63+
}
64+
}
65+
66+
return ret
67+
}
68+
69+
// Answer: [[-1, 0, 1], [-1, -1, 2]]
70+
threeSum([-1, 0, 1, 2, -1, -4], target: 0)
5471

5572
// Answer: [[-1, -1, 2], [-1, 0, 1]]
56-
ThreeSum([-1, -1, -1, -1, 2, 1, -4, 0], targetSum: 0)
73+
threeSum([-1, -1, -1, -1, 2, 1, -4, 0], target: 0)
5774

5875
// Answer: [[-1, -1, 2]]
59-
ThreeSum([-1, -1, -1, -1, -1, -1, 2], targetSum: 0)
76+
threeSum([-1, -1, -1, -1, -1, -1, 2], target: 0)

0 commit comments

Comments
 (0)