zoukankan      html  css  js  c++  java
  • [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] 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 + "" }
    502         if node.left == nil && node.right == nil {
    503             return root + "■(node)
    "
    504         }
    505         return diagram(for: node.right, top: top + "  ", root: top + "┌─", bottom: top + "") +
    506             root + "■(node)
    " +
    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 += "
    " } }
    613             guard let element = array[head + offset] else { continue }
    614             desc += "
    	[(offset)] (element)"
    615         }
    616         desc += ")"
    617         return desc
    618     }
    619     
    620     public var debugDescription: String {
    621         return description
    622     }
    623 }
  • 相关阅读:
    Upgrading CentOS 6 to CentOS 7
    redis主从同步错误处理
    【linux】free命令中cached和buffers的区别
    服务器TIME_WAIT和CLOSE_WAIT区别及解决方案
    msyql 主从切换
    MySQL主从同步报错1507
    MYSQL SHOW 用法
    NGINX中的proxy_pass和rewrite
    Web服务器Nginx多方位优化策略
    operator重载运算符
  • 原文地址:https://www.cnblogs.com/strengthen/p/10262689.html
Copyright © 2011-2022 走看看