为有牺牲多壮志,敢教日月换新天。

[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 
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

热烈欢迎,请直接点击!!!

进入博主App Store主页,下载使用各个作品!!!

注:博主将坚持每月上线一个新app!!!

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] and A[j] is the smallest possible value.  If there are multiple such indexes j, you can only jump to the smallest such index j.
  • During even numbered jumps (ie. jumps 2, 4, 6, ...), you jump to the index j such that A[i] >= A[j] and A[j] is the largest possible value.  If there are multiple such indexes j, you can only jump to the smallestsuch index j.
  • (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. 1 <= A.length <= 20000
  2. 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. 1 <= A.length <= 20000
  2. 0 <= A[i] < 100000

Runtime: 224 ms
Memory Usage: 22.1 MB
 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 }

 

posted @ 2019-01-13 15:29  为敢技术  阅读(514)  评论(0编辑  收藏  举报