[Swift]LeetCode975. 奇偶跳 | Odd Even Jump
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(shanqingyongzhi)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:https://www.cnblogs.com/strengthen/p/10262689.html
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
You are given an integer array A
. From some starting index, you can make a series of jumps. The (1st, 3rd, 5th, ...) jumps in the series are called odd numbered jumps, and the (2nd, 4th, 6th, ...) jumps in the series are called even numbered jumps.
You may from index i
jump forward to index j
(with i < j
) in the following way:
- During odd numbered jumps (ie. jumps 1, 3, 5, ...), you jump to the index j such that
A[i] <= A[j]
andA[j]
is the smallest possible value. If there are multiple such indexesj
, you can only jump to the smallest such indexj
. - During even numbered jumps (ie. jumps 2, 4, 6, ...), you jump to the index j such that
A[i] >= A[j]
andA[j]
is the largest possible value. If there are multiple such indexesj
, you can only jump to the smallestsuch indexj
. - (It may be the case that for some index
i,
there are no legal jumps.)
A starting index is good if, starting from that index, you can reach the end of the array (index A.length - 1
) by jumping some number of times (possibly 0 or more than once.)
Return the number of good starting indexes.
Example 1:
Input: [10,13,12,14,15]
Output: 2
Explanation:
From starting index i = 0, we can jump to i = 2 (since A[2] is the smallest among A[1], A[2], A[3], A[4] that is greater or equal to A[0]), then we can't jump any more.
From starting index i = 1 and i = 2, we can jump to i = 3, then we can't jump any more.
From starting index i = 3, we can jump to i = 4, so we've reached the end.
From starting index i = 4, we've reached the end already.
In total, there are 2 different starting indexes (i = 3, i = 4) where we can reach the end with some number of jumps.
Example 2:
Input: [2,3,1,1,4]
Output: 3
Explanation:
From starting index i = 0, we make jumps to i = 1, i = 2, i = 3:
During our 1st jump (odd numbered), we first jump to i = 1 because A[1] is the smallest value in (A[1], A[2], A[3], A[4]) that is greater than or equal to A[0].
During our 2nd jump (even numbered), we jump from i = 1 to i = 2 because A[2] is the largest value in (A[2], A[3], A[4]) that is less than or equal to A[1]. A[3] is also the largest value, but 2 is a smaller index, so we can only jump to i = 2 and not i = 3.
During our 3rd jump (odd numbered), we jump from i = 2 to i = 3 because A[3] is the smallest value in (A[3], A[4]) that is greater than or equal to A[2].
We can't jump from i = 3 to i = 4, so the starting index i = 0 is not good.
In a similar manner, we can deduce that:
From starting index i = 1, we jump to i = 4, so we reach the end.
From starting index i = 2, we jump to i = 3, and then we can't jump anymore.
From starting index i = 3, we jump to i = 4, so we reach the end.
From starting index i = 4, we are already at the end.
In total, there are 3 different starting indexes (i = 1, i = 3, i = 4) where we can reach the end with some number of jumps.
Example 3:
Input: [5,1,3,4,2]
Output: 3
Explanation:
We can reach the end from starting indexes 1, 2, and 4.
Note:
1 <= A.length <= 20000
0 <= A[i] < 100000
给定一个整数数组 A
,你可以从某一起始索引出发,跳跃一定次数。在你跳跃的过程中,第 1、3、5... 次跳跃称为奇数跳跃,而第 2、4、6... 次跳跃称为偶数跳跃。
你可以按以下方式从索引 i
向后跳转到索引 j
(其中 i < j
):
- 在进行奇数跳跃时(如,第 1,3,5... 次跳跃),你将会跳到索引
j
,使得A[i] <= A[j]
,A[j]
是可能的最小值。如果存在多个这样的索引j
,你只能跳到满足要求的最小索引j
上。 - 在进行偶数跳跃时(如,第 2,4,6... 次跳跃),你将会跳到索引
j
,使得A[i] => A[j]
,A[j]
是可能的最大值。如果存在多个这样的索引j
,你只能跳到满足要求的最小索引j
上。 - (对于某些索引
i
,可能无法进行合乎要求的跳跃。)
如果从某一索引开始跳跃一定次数(可能是 0 次或多次),就可以到达数组的末尾(索引 A.length - 1
),那么该索引就会被认为是好的起始索引。
返回好的起始索引的数量。
示例 1:
输入:[10,13,12,14,15] 输出:2 解释: 从起始索引 i = 0 出发,我们可以跳到 i = 2,(因为 A[2] 是 A[1],A[2],A[3],A[4] 中大于或等于 A[0] 的最小值),然后我们就无法继续跳下去了。 从起始索引 i = 1 和 i = 2 出发,我们可以跳到 i = 3,然后我们就无法继续跳下去了。 从起始索引 i = 3 出发,我们可以跳到 i = 4,到达数组末尾。 从起始索引 i = 4 出发,我们已经到达数组末尾。 总之,我们可以从 2 个不同的起始索引(i = 3, i = 4)出发,通过一定数量的跳跃到达数组末尾。
示例 2:
输入:[2,3,1,1,4] 输出:3 解释: 从起始索引 i=0 出发,我们依次可以跳到 i = 1,i = 2,i = 3: 在我们的第一次跳跃(奇数)中,我们先跳到 i = 1,因为 A[1] 是(A[1],A[2],A[3],A[4])中大于或等于 A[0] 的最小值。 在我们的第二次跳跃(偶数)中,我们从 i = 1 跳到 i = 2,因为 A[2] 是(A[2],A[3],A[4])中小于或等于 A[1] 的最大值。A[3] 也是最大的值,但 2 是一个较小的索引,所以我们只能跳到 i = 2,而不能跳到 i = 3。 在我们的第三次跳跃(奇数)中,我们从 i = 2 跳到 i = 3,因为 A[3] 是(A[3],A[4])中大于或等于 A[2] 的最小值。 我们不能从 i = 3 跳到 i = 4,所以起始索引 i = 0 不是好的起始索引。 类似地,我们可以推断: 从起始索引 i = 1 出发, 我们跳到 i = 4,这样我们就到达数组末尾。 从起始索引 i = 2 出发, 我们跳到 i = 3,然后我们就不能再跳了。 从起始索引 i = 3 出发, 我们跳到 i = 4,这样我们就到达数组末尾。 从起始索引 i = 4 出发,我们已经到达数组末尾。 总之,我们可以从 3 个不同的起始索引(i = 1, i = 3, i = 4)出发,通过一定数量的跳跃到达数组末尾。
示例 3:
输入:[5,1,3,4,2] 输出:3 解释: 我们可以从起始索引 1,2,4 出发到达数组末尾。
提示:
1 <= A.length <= 20000
0 <= A[i] < 100000
1 class Solution { 2 func oddEvenJumps(_ A: [Int]) -> Int { 3 var A = A 4 let maxNum:Int = rerange(&A) 5 var map:[Int] = [Int](repeating:0,count:maxNum + 1) 6 var res:Int = 1 7 let N:Int = A.count 8 map[A[N-1]] = N-1 9 var odds:[Bool] = [Bool](repeating:false,count:N) 10 var evens:[Bool] = [Bool](repeating:false,count:N) 11 odds[N-1] = true 12 evens[N-1] = true 13 for i in stride(from:N - 2,through:0,by: -1) 14 { 15 let key:Int = A[i] 16 let minGE:Int = ceilingIndex(map,key) 17 let maxLE:Int = floorIndex(map,key) 18 if minGE != 0 && evens[minGE] 19 { 20 res += 1 21 odds[i] = true 22 } 23 if maxLE != 0 && odds[maxLE] 24 { 25 evens[i] = true 26 } 27 map[key] = i 28 } 29 return res 30 } 31 32 func rerange(_ A:inout [Int]) -> Int { 33 var minNum:Int = A[0] 34 var maxNum:Int = A[0] 35 for v in A 36 { 37 if v < minNum {minNum = v} 38 if v > maxNum {maxNum = v} 39 } 40 var map:[Int] = [Int](repeating:0,count:maxNum - minNum + 1) 41 for v in A 42 { 43 map[v - minNum] = 1 44 } 45 var ix:Int = 0 46 for i in 0..<map.count 47 { 48 if map[i] != 0 49 { 50 ix += 1 51 map[i] = ix 52 } 53 } 54 for i in 0..<A.count 55 { 56 A[i] = map[A[i] - minNum] 57 } 58 return ix 59 } 60 61 func ceilingIndex(_ map:[Int],_ v:Int) -> Int 62 { 63 var v = v 64 while(v < map.count) 65 { 66 if map[v] != 0 67 { 68 return map[v] 69 } 70 v += 1 71 } 72 return 0 73 } 74 75 func floorIndex(_ map:[Int],_ v:Int) -> Int 76 { 77 var v = v 78 while(v > 0) 79 { 80 if map[v] != 0 81 { 82 return map[v] 83 } 84 v -= 1 85 } 86 return 0 87 } 88 }
428ms
1 class Solution { 2 func oddEvenJumps(_ A: [Int]) -> Int { 3 var nextHigher = Array(repeating: 0, count: A.count) 4 var stack = [Int]() 5 for (i, a) in ((A.enumerated()).sorted { $0.1 < $1.1 }) { 6 while !stack.isEmpty && stack.last! < i { 7 nextHigher[stack.removeLast()] = i 8 } 9 stack.append(i) 10 } 11 12 var nextLower = Array(repeating: 0, count: A.count) 13 stack = [] 14 for (i, a) in ((A.enumerated()).sorted { $0.1 > $1.1 }) { 15 while !stack.isEmpty && stack.last! < i { 16 nextLower[stack.removeLast()] = i 17 } 18 stack.append(i) 19 } 20 21 var higher = Array(repeating: 0, count: A.count) 22 var lower = Array(repeating: 0, count: A.count) 23 higher[A.count-1] = 1 24 lower[A.count-1] = 1 25 for i in (0..<(A.count - 1)).reversed() { 26 higher[i] = lower[nextHigher[i]] 27 lower[i] = higher[nextLower[i]] 28 } 29 30 return higher.reduce(0, +) 31 } 32 }
444ms
1 class Solution { 2 func oddEvenJumps(_ A: [Int]) -> Int { 3 guard A.count > 1 else { return A.count } 4 5 var map = [(Int, Int)]() 6 for (index, item) in A.enumerated() { 7 map.append((item, index)) 8 } 9 10 let nextHeigher = generateNextHeigher(map) 11 let nextLower = generateNextLower(map) 12 13 var heigher = Array(repeating: 0, count: A.count) 14 var lower = Array(repeating: 0, count: A.count) 15 heigher[A.count - 1] = 1 16 lower[A.count - 1] = 1 17 18 for i in (0..<A.count - 1).reversed() { 19 heigher[i] = lower[nextHeigher[i]] 20 lower[i] = heigher[nextLower[i]] 21 } 22 23 return heigher.reduce(0, +) 24 25 } 26 27 func generateNextHeigher(_ map: [(Int, Int)]) -> [Int] { 28 let map = map.sorted { 29 if $0.0 == $1.0 { return $0.1 < $1.1 } 30 return $0.0 < $1.0 31 } 32 33 var nextHeigher = Array(repeating: 0, count: map.count) 34 var stack = [Int]() 35 36 for (item, index) in map { 37 while stack.count > 0 && stack.last! < index { 38 nextHeigher[stack.popLast()!] = index 39 } 40 stack.append(index) 41 } 42 43 return nextHeigher 44 } 45 46 func generateNextLower(_ map: [(Int, Int)]) -> [Int] { 47 let map = map.sorted { 48 if $0.0 == $1.0 { return $0.1 < $1.1 } 49 return $0.0 > $1.0 50 } 51 52 var nextLower = Array(repeating: 0, count: map.count) 53 var stack = [Int]() 54 55 for (item, index) in map { 56 while stack.count > 0 && stack.last! < index { 57 nextLower[stack.popLast()!] = index 58 } 59 stack.append(index) 60 } 61 62 return nextLower 63 } 64 }
800ms
1 class Solution { 2 private struct Record: CustomStringConvertible { 3 var oddFeasible: Bool 4 var evenFeasible: Bool 5 6 init() { 7 self.oddFeasible = false 8 self.evenFeasible = false 9 } 10 11 var description: String { 12 return "\(oddFeasible) + \(evenFeasible)" 13 } 14 } 15 16 func oddEvenJumps(_ A: [Int]) -> Int { 17 let path = searchPath(A) 18 var records = [Record]() 19 20 var lastRecord = Record() 21 lastRecord.oddFeasible = true 22 lastRecord.evenFeasible = true 23 records.append(lastRecord) 24 25 for idx in stride(from: A.count-1, to: 0, by: -1) { 26 var record = Record() 27 28 let nextJumpByOdd = path.oddPath[idx-1] 29 if nextJumpByOdd >= 0 { 30 record.oddFeasible = records[A.count - 1 - nextJumpByOdd].evenFeasible 31 } else { 32 record.oddFeasible = false 33 } 34 35 let nextJumpByEven = path.evenPath[idx-1] 36 if nextJumpByEven >= 0 { 37 record.evenFeasible = records[A.count - 1 - nextJumpByEven].oddFeasible 38 } else { 39 record.evenFeasible = false 40 } 41 42 records.append(record) 43 } 44 45 return records.reduce(0) { 46 if $1.oddFeasible { 47 return $0 + 1 48 } else { 49 return $0 50 } 51 } 52 } 53 54 struct Path { 55 var evenPath: [Int] 56 var oddPath: [Int] 57 58 init() { 59 oddPath = [] 60 evenPath = [] 61 } 62 } 63 64 struct Node: Comparable, Equatable { 65 let num: Int 66 let idx: Int 67 68 static func <(_ lhs: Node, _ rhs: Node) -> Bool { 69 return lhs.num < rhs.num 70 } 71 72 static func ==(_ lhs: Node, _ rhs: Node) -> Bool { 73 return lhs.num == rhs.num 74 } 75 } 76 77 private func searchPath(_ A: [Int]) -> Path { 78 var path = Path() 79 var sortedSuffix = [Node]() 80 81 for idx in stride(from: A.count, to: 0, by: -1) { 82 let node = Node(num: A[idx-1], idx: idx-1) 83 let index = sortedSuffix.sortedInsert(node) 84 if index < sortedSuffix.count-1 { 85 let rightNode = sortedSuffix[index+1] 86 path.oddPath.insert(rightNode.idx, at: 0) 87 if rightNode == node { 88 path.evenPath.insert(rightNode.idx, at: 0) 89 continue 90 } 91 } else { 92 path.oddPath.insert(-1, at: 0) 93 } 94 95 if index > 0 { 96 let leftVal = sortedSuffix[index - 1] 97 var leftIdx = index - 2 98 while leftIdx >= 0 && leftVal == sortedSuffix[leftIdx] { 99 leftIdx = leftIdx - 1 100 } 101 102 let leftNode = sortedSuffix[leftIdx + 1] 103 path.evenPath.insert(leftNode.idx, at: 0) 104 } else { 105 path.evenPath.insert(-1, at: 0) 106 } 107 } 108 109 return path 110 } 111 } 112 113 extension Array where Element: Comparable { 114 mutating func sortedInsert(_ elm: Element) -> Int { 115 if count == 0 { 116 append(elm) 117 return 0 118 } 119 120 if count == 1 { 121 if elm <= self[0] { 122 insert(elm, at: 0) 123 return 0 124 } else { 125 append(elm) 126 return 1 127 } 128 } 129 130 if count > 1 { 131 if elm <= self[0] { 132 insert(elm, at: 0) 133 return 0 134 } else if elm > self[count-1] { 135 insert(elm, at: count) 136 return count-1 137 } 138 } 139 140 let idx = binarySearch(elm, 0, count-1) 141 insert(elm, at: idx) 142 return idx 143 } 144 145 // Invariant: start < elm, end >= elm, end != start 146 private func binarySearch(_ elm: Element, _ start: Int, _ end: Int) -> Int { 147 if end - start == 1 { 148 return end 149 } 150 151 let mid: Int = (start + end) / 2 152 if self[mid] < elm { 153 return binarySearch(elm, mid, end) 154 } else if self[mid] > elm { 155 return binarySearch(elm, start, mid) 156 } else { 157 return mid 158 } 159 } 160 }
2328ms
1 class Solution { 2 func oddEvenJumps(_ A: [Int]) -> Int { 3 guard A.count > 0 else { return 0 } 4 5 var map = [Int: Int]() 6 7 let tree = AVLTree<Int>() 8 9 var minMaxArr: [Int?] = Array(repeating: nil, count: A.count) 10 var maxMinArr: [Int?] = Array(repeating: nil, count: A.count) 11 12 var i = A.count - 1 13 while i >= 0 { 14 let this = A[i] 15 16 if let node = tree.root?.find(to: this, rule: .closestRight) { 17 minMaxArr[i] = map[node.value] 18 } 19 20 if let node = tree.root?.find(to: this, rule: .closestLeft) { 21 maxMinArr[i] = map[node.value] 22 } 23 24 tree.add(value: this) 25 map[this] = i 26 i -= 1 27 } 28 29 var odd = Array(repeating: 0, count: A.count) 30 var even = Array(repeating: 1, count: A.count) 31 32 for i in 0..<A.count { 33 if even[i] > 0, let smallestLarger = minMaxArr[i] { 34 odd[smallestLarger] += even[i] 35 } 36 37 if odd[i] > 0, let largestSmaller = maxMinArr[i] { 38 even[largestSmaller] += odd[i] 39 } 40 } 41 42 return odd[A.count - 1] + even[A.count - 1] 43 } 44 } 45 46 47 48 49 open class AVLTree<ValueT: Comparable>: Equatable { 50 // MARK: - Properties 51 fileprivate(set) var root: Node? 52 53 // MARK: - Operations 54 public var height: Int { return root?.height ?? -1 } 55 public var isEmpty: Bool { return root == nil } 56 57 /// - Complexity: O(n) 58 public var count: Int { return root?.count ?? 0 } 59 60 /// Override to provide a different node type 61 open func node(for value: ValueT) -> Node { 62 return Node(value: value) 63 } 64 65 /// Returns `false` when no insertion was performed. 66 /// - Complexity: O(log n) 67 @discardableResult 68 open func add(node: Node) -> Bool { 69 guard node.tree == nil || node.tree === self else { 70 assertionFailure("Node already belongs to another tree") 71 return false 72 } 73 74 node.tree = self 75 guard let root = root else { 76 self.root = node 77 return true 78 } 79 return root.add(node: node) 80 } 81 82 /// - Complexity: O(log n) 83 public func add(value: ValueT) { 84 add(node: node(for: value)) 85 } 86 87 /// - Complexity: O(log n) 88 public func find(value: ValueT) -> Node? { 89 return root?.find(to: value, rule: .exact) 90 } 91 92 /// - Complexity: O(*log n*) 93 public func min() -> ValueT? { return root?.findMin()?.value } 94 /// - Complexity: O(*log n*) 95 public func max() -> ValueT? { return root?.findMax()?.value } 96 97 /// - Complexity: O(log n) 98 open func remove(node: Node) { 99 guard node.ancestor === root else { 100 // Must be a node under this tree 101 return 102 } 103 104 defer { 105 node.parent?.updateProperties() 106 node.parent?.restoreBalanceAfterRemoval() 107 } 108 109 switch (node.left, node.right) { 110 case (nil, nil): 111 // No children, no-one will mourn its demise 112 node.replaceInParent(with: nil) 113 114 case let (leftChild, nil): 115 // Heir to the throne 116 node.replaceInParent(with: leftChild) 117 case let (nil, rightChild): 118 node.replaceInParent(with: rightChild) 119 120 default: 121 guard let successor = node.successor else { 122 return 123 } 124 remove(node: successor) 125 successor.left = node.left 126 successor.right = node.right 127 // Old node is dead, long live the successor 128 node.replaceInParent(with: successor) 129 130 successor.updateProperties() 131 } 132 } 133 134 /// - Complexity: O(1) 135 open func removeAll() { 136 root = nil // Ez game 137 } 138 139 /// - Complexity: O(log n) 140 @discardableResult 141 public func remove(value: ValueT) -> Node? { 142 guard let removedNode = root?.find(to: value, rule: .exact) else { 143 return nil 144 } 145 remove(node: removedNode) 146 return removedNode 147 } 148 149 // MARK: - Node Class 150 open class Node: Equatable, CustomStringConvertible { 151 public let value: ValueT 152 153 fileprivate(set) weak var parent: Node? 154 fileprivate(set) weak var tree: AVLTree<ValueT>? 155 public fileprivate(set) var left: Node? { 156 didSet { left?.parent = self } 157 } 158 public fileprivate(set) var right: Node? { 159 didSet { right?.parent = self } 160 } 161 public private(set) var height: Int = 0 162 163 public init(value: ValueT) { 164 self.value = value 165 } 166 167 open func node(for value: ValueT) -> AVLTree.Node { 168 return AVLTree.Node(value: value) 169 } 170 171 open func updateProperties() { 172 updateHeight() 173 } 174 175 // MARK: CustomStringConvertible 176 public var description: String { 177 return String(describing: value) 178 } 179 } 180 } 181 182 // MARK: - Node Implementations 183 extension AVLTree.Node { 184 public var isRoot: Bool { return parent == nil } 185 186 public var ancestor: AVLTree.Node { 187 return parent?.ancestor ?? self 188 } 189 190 /// - Complexity: O(n) 191 public var count: Int { 192 return 1 + (left?.count ?? 0) + (right?.count ?? 0) 193 } 194 195 var leftHeight: Int { return left?.height ?? -1 } 196 var rightHeight: Int { return right?.height ?? -1 } 197 198 @discardableResult 199 func add(node: AVLTree.Node) -> Bool { 200 guard self.value != node.value else { 201 // Value already exists 202 return false 203 } 204 205 var didInsert = false 206 207 if node.value < self.value { 208 if let left = left { 209 didInsert = left.add(node: node) 210 } else { 211 left = node 212 node.parent = self 213 didInsert = true 214 } 215 } else { 216 if let right = right { 217 didInsert = right.add(node: node) 218 } else { 219 right = node 220 node.parent = self 221 didInsert = true 222 } 223 } 224 guard didInsert else { return false } 225 226 updateProperties() 227 restoreBalance() 228 return true 229 } 230 231 private func updateHeight() { 232 height = max(left?.height ?? -1, right?.height ?? -1) + 1 233 } 234 235 func add(value: ValueT) { 236 add(node: node(for: value)) 237 } 238 239 enum QueryRule { 240 case exact 241 case closest 242 case closestLeft 243 case closestRight 244 } 245 246 func find(to value: ValueT, rule: QueryRule) -> AVLTree.Node? { 247 if value == self.value { return self } 248 switch rule { 249 case .exact: 250 if value < self.value { 251 return left?.find(to: value, rule: rule) 252 } else { 253 return right?.find(to: value, rule: rule) 254 } 255 case .closest: 256 if value < self.value { 257 return left?.find(to: value, rule: rule) ?? self 258 } else { 259 return right?.find(to: value, rule: rule) ?? self 260 } 261 case .closestLeft: 262 if value < self.value { 263 return left?.find(to: value, rule: rule) 264 } else { 265 return right?.find(to: value, rule: rule) ?? self 266 } 267 case .closestRight: 268 if value < self.value { 269 return left?.find(to: value, rule: rule) ?? self 270 } else { 271 return right?.find(to: value, rule: rule) 272 } 273 } 274 } 275 276 func replaceInParent(with anotherNode: AVLTree.Node?) { 277 if let parent = parent { 278 if parent.left?.value == self.value { 279 parent.left = anotherNode 280 anotherNode?.parent = parent 281 } else if parent.right?.value == self.value { 282 parent.right = anotherNode 283 anotherNode?.parent = parent 284 } 285 } 286 // Self is root! Update the tree instead 287 else if let tree = tree, tree.root?.value == self.value { 288 tree.root = anotherNode 289 anotherNode?.parent = nil 290 } 291 } 292 293 func findMin() -> AVLTree.Node? { 294 guard let left = left else { return self } 295 return left.findMin() 296 } 297 298 func findMax() -> AVLTree.Node? { 299 guard let right = right else { return self } 300 return right.findMax() 301 } 302 } 303 304 // MARK: - Traversals 305 extension AVLTree { 306 enum Traversal { 307 case preOrder 308 case inOrder 309 case postOrder 310 } 311 312 func traverse(_ traversal: Traversal, execute block: (AVLTree.Node) -> Void) { 313 guard let root = root else { return } 314 switch traversal { 315 case .inOrder: root.traverseInOrder(execute: block) 316 case .preOrder: root.traversePreOrder(execute: block) 317 case .postOrder: root.traversePostOrder(execute: block) 318 } 319 } 320 } 321 322 extension AVLTree.Node { 323 fileprivate func traverseInOrder(execute block: (AVLTree.Node) -> Void) { 324 left?.traverseInOrder(execute: block) 325 block(self) 326 right?.traverseInOrder(execute: block) 327 } 328 329 fileprivate func traversePreOrder(execute block: (AVLTree.Node) -> Void) { 330 block(self) 331 left?.traversePreOrder(execute: block) 332 right?.traversePreOrder(execute: block) 333 } 334 335 fileprivate func traversePostOrder(execute block: (AVLTree.Node) -> Void) { 336 left?.traversePostOrder(execute: block) 337 right?.traversePostOrder(execute: block) 338 block(self) 339 } 340 } 341 342 // MARK: - More Operations 343 extension AVLTree { 344 func findSuccessor(of value: ValueT) -> AVLTree.Node? { 345 guard let root = root else { return nil } 346 let closestNode = root.find(to: value, rule: .closest)! 347 if closestNode.value > value { return closestNode } 348 349 guard let closestSuccesor = closestNode.successor else { return nil } 350 return closestSuccesor.value > value ? closestSuccesor : nil 351 } 352 353 func findPredecessor(of value: ValueT) -> AVLTree.Node? { 354 guard let root = root else { return nil } 355 let closestNode = root.find(to: value, rule: .closest)! 356 if closestNode.value < value { return closestNode } 357 358 guard let closestPredecessor = closestNode.predecessor else { return nil } 359 return closestPredecessor.value < value ? closestPredecessor : nil 360 } 361 } 362 363 extension AVLTree.Node { 364 var successor: AVLTree.Node? { 365 if let right = right { return right.findMin() } 366 367 var currentParent = parent 368 var currentChild = self 369 while let parent = currentParent, currentChild.value == parent.right?.value { 370 currentChild = parent 371 currentParent = currentChild.parent 372 } 373 return currentParent 374 } 375 376 var predecessor: AVLTree.Node? { 377 if let left = left { return left.findMax() } 378 379 var currentParent = parent 380 var currentChild = self 381 while let parent = currentParent, currentChild.value == parent.left?.value { 382 currentChild = parent 383 currentParent = currentChild.parent 384 } 385 return currentParent 386 } 387 } 388 389 // MARK: - Rotations 390 fileprivate extension AVLTree.Node { 391 private var isOutOfBalance: Bool { 392 return abs(leftHeight - rightHeight) > 1 393 } 394 395 private enum BalanceState { 396 case perfectlyBalanced 397 case leftHeavy 398 case rightHeavy 399 } 400 401 private var balanceState: BalanceState { 402 let diff = leftHeight - rightHeight 403 if diff == 0 { return .perfectlyBalanced } 404 else if diff > 0 { return .leftHeavy } 405 else { return .rightHeavy } 406 } 407 408 private func restoreBalance() { 409 guard isOutOfBalance else { return } 410 411 if let left = left, left.isOutOfBalance { 412 left.restoreBalance() 413 } 414 if let right = right, right.isOutOfBalance { 415 right.restoreBalance() 416 } 417 418 // It is `self` that needs to balance itself 419 if case .leftHeavy = balanceState, let left = left { 420 switch left.balanceState { 421 case .perfectlyBalanced, .leftHeavy: 422 rotateRight() 423 case .rightHeavy: 424 left.rotateLeft() 425 rotateRight() 426 } 427 } else if case .rightHeavy = balanceState, let right = right { 428 switch right.balanceState { 429 case .perfectlyBalanced, .rightHeavy: 430 rotateLeft() 431 case .leftHeavy: 432 right.rotateRight() 433 rotateLeft() 434 } 435 } 436 } 437 438 fileprivate func restoreBalanceAfterRemoval() { 439 restoreBalance() 440 441 guard let parent = parent else { return } 442 parent.updateProperties() 443 parent.restoreBalanceAfterRemoval() 444 } 445 446 private func rotateRight() { 447 guard let left = left else { return } 448 449 left.parent = self.parent 450 self.replaceInParent(with: left) 451 self.parent = left 452 self.left = left.right 453 left.right = self 454 455 updateProperties() 456 left.updateProperties() 457 } 458 459 private func rotateLeft() { 460 guard let right = right else { return } 461 462 right.parent = self.parent 463 self.replaceInParent(with: right) 464 self.parent = right 465 self.right = right.left 466 right.left = self 467 468 updateProperties() 469 right.updateProperties() 470 } 471 } 472 473 // MARK: - Equatable 474 extension AVLTree { 475 public static func == (lhs: AVLTree, rhs: AVLTree) -> Bool { 476 return lhs.root == rhs.root 477 } 478 } 479 480 extension AVLTree.Node { 481 public static func == (lhs: AVLTree.Node, rhs: AVLTree.Node) -> Bool { 482 return lhs.value == rhs.value && lhs.left == rhs.left && lhs.right == rhs.right 483 } 484 } 485 486 // MARK: - Sequence 487 extension AVLTree: Sequence { 488 public typealias Element = ValueT 489 public typealias Iterator = Queue<ValueT> 490 491 public func makeIterator() -> AVLTree<ValueT>.Iterator { 492 var queue = Queue<ValueT>() 493 traverse(.inOrder) { node in queue.enqueue(node.value) } 494 return queue 495 } 496 } 497 498 // MARK: - Debugging 499 extension AVLTree: CustomStringConvertible { 500 private func diagram<ValueT>(for node: AVLTree<ValueT>.Node?, top: String = "", root: String = "", bottom: String = "") -> String { 501 guard let node = node else { return root + "•\n" } 502 if node.left == nil && node.right == nil { 503 return root + "■\(node)\n" 504 } 505 return diagram(for: node.right, top: top + " ", root: top + "┌─", bottom: top + "│ ") + 506 root + "■\(node)\n" + 507 diagram(for: node.left, top: bottom + "│ ", root: bottom + "└─", bottom: bottom + " ") 508 509 } 510 511 public var description: String { 512 return diagram(for: root) 513 } 514 } 515 516 public struct Queue<T> { 517 fileprivate var array: [T?] 518 fileprivate var head = 0 519 520 public init(_ array: [T?] = [T?]()) { 521 self.array = array 522 } 523 524 public var isEmpty: Bool { 525 return count == 0 526 } 527 528 public var count: Int { 529 return array.count - head 530 } 531 532 public mutating func enqueue(_ element: T) { 533 array.append(element) 534 } 535 536 public mutating func dequeue() -> T? { 537 guard head < array.count, let element = array[head] else { return nil } 538 539 array[head] = nil 540 head += 1 541 542 let percentage = Double(head)/Double(array.count) 543 if array.count > 50 && percentage > 0.25 { 544 array.removeFirst(head) 545 head = 0 546 } 547 548 return element 549 } 550 551 public var front: T? { 552 if isEmpty { 553 return nil 554 } else { 555 return array[head] 556 } 557 } 558 559 @discardableResult 560 public mutating func removeAll() -> [T] { 561 let elements = array[head..<array.count] 562 array = [] 563 head = 0 564 return elements.compactMap { $0 } 565 } 566 567 public func clone() -> Queue<T> { 568 var clone = Queue<T>() 569 clone.array = Array(array[head..<array.count]) 570 assert(clone.head == 0) 571 return clone 572 } 573 } 574 575 // MARK: - Codable 576 extension Queue: Codable where T: Codable { 577 public func encode(to encoder: Encoder) throws { 578 var container = encoder.singleValueContainer() 579 if head == 0 { 580 try container.encode(array.compactMap { $0 }) 581 } else { 582 try container.encode(Array(array[head..<array.count].compactMap { $0 })) 583 } 584 } 585 586 public init(from decoder: Decoder) throws { 587 head = 0 588 let container = try decoder.singleValueContainer() 589 array = try container.decode([T].self) 590 } 591 } 592 593 // MARK: - Sequence 594 extension Queue: Sequence { 595 public func makeIterator() -> Queue<T> { 596 return clone() 597 } 598 } 599 600 extension Queue: IteratorProtocol { 601 public typealias Element = T 602 603 public mutating func next() -> T? { 604 return dequeue() 605 } 606 } 607 608 extension Queue: CustomStringConvertible, CustomDebugStringConvertible { 609 public var description: String { 610 var desc: String = "(" 611 for offset in 0..<count { 612 defer { if offset == count - 1 { desc += "\n" } } 613 guard let element = array[head + offset] else { continue } 614 desc += "\n\t[\(offset)] \(element)" 615 } 616 desc += ")" 617 return desc 618 } 619 620 public var debugDescription: String { 621 return description 622 } 623 }