[Swift]LeetCode407. 接雨水 II | Trapping Rain Water II

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:为敢(WeiGanTechnologies)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:https://www.cnblogs.com/strengthen/p/10329251.html 
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

Given an m x n matrix of positive integers representing the height of each unit cell in a 2D elevation map, compute the volume of water it is able to trap after raining. 

Note:

Both m and n are less than 110. The height of each unit cell is greater than 0 and is less than 20,000. 

Example:

Given the following 3x6 height map:
[
  [1,4,3,1,3,2],
  [3,2,1,3,2,4],
  [2,3,3,2,3,1]
]

Return 4.

The above image represents the elevation map [[1,4,3,1,3,2],[3,2,1,3,2,4],[2,3,3,2,3,1]] before the rain. 

After the rain, water is trapped between the blocks. The total volume of water trapped is 4.


给定一个 m x n 的矩阵,其中的值均为正整数,代表二维高度图每个单元的高度,请计算图中形状最多能接多少体积的雨水。 

说明:

和 都是小于110的整数。每一个单位的高度都大于0 且小于 20000。 

示例:

给出如下 3x6 的高度图:
[
  [1,4,3,1,3,2],
  [3,2,1,3,2,4],
  [2,3,3,2,3,1]
]
返回 4。

如上图所示,这是下雨前的高度图[[1,4,3,1,3,2],[3,2,1,3,2,4],[2,3,3,2,3,1]] 的状态。 

下雨后,雨水将会被存储在这些方块中。总的接雨水量是4。


Runtime: 256 ms
Memory Usage: 19.1 MB
  1 class Solution {
  2     func trapRainWater(_ heightMap: [[Int]]) -> Int {
  3         if heightMap.isEmpty {return 0}
  4         var m:Int = heightMap.count
  5         var n:Int = heightMap[0].count
  6         var res:Int = 0
  7         var mx:Int = Int.min
  8         var q = Heap<(Int, Int)>.init { (f, s) -> Bool in
  9             if f.0 == s.0
 10             {
 11                 return f.1 < s.1
 12             }
 13             return f.0 < s.0
 14         }
 15         var visited:[[Bool]] = [[Bool]](repeating:[Bool](repeating:false,count:n),count:m)
 16         var dir:[[Int]] = [[0,-1],[-1,0],[0,1],[1,0]]
 17         for i in 0..<m
 18         {
 19             for j in 0..<n
 20             {
 21                 if i == 0 || i == m - 1 || j == 0 || j == n - 1
 22                 {
 23                     q.insert((heightMap[i][j], i * n + j))
 24                     visited[i][j] = true
 25                 }
 26             }
 27         }
 28         while(!q.isEmpty)
 29         {
 30             var t:(Int, Int) = q.remove()!
 31             var h:Int = t.0
 32             var r:Int = t.1 / n
 33             var c:Int = t.1 % n
 34             mx = max(mx, h)
 35             for i in 0..<dir.count
 36             {
 37                 var x:Int = r + dir[i][0]
 38                 var y:Int = c + dir[i][1]
 39                 if x < 0 || x >= m || y < 0 || y >= n || visited[x][y]
 40                 {
 41                     continue
 42                 }
 43                 visited[x][y] = true
 44                 if heightMap[x][y] < mx
 45                 {
 46                     res += mx - heightMap[x][y]
 47                 }
 48                 q.insert((heightMap[x][y], x * n + y))
 49             }
 50         }
 51         return res
 52     }
 53 }
 54 
 55 public struct Heap<T> {
 56     public var nodes = [T]()
 57     private var orderCriteria: (T, T) -> Bool
 58     
 59     public init(sort: @escaping (T, T) -> Bool) {
 60         orderCriteria = sort
 61     }
 62     
 63     public init(array: [T], sort: @escaping (T, T) -> Bool) {
 64         self.orderCriteria = sort
 65         configureHeap(from: array)
 66     }
 67     
 68     public var isEmpty: Bool {
 69         return nodes.isEmpty
 70     }
 71     
 72     public var count: Int {
 73         return nodes.count
 74     }
 75     
 76     public mutating func configureHeap(from array: [T]) {
 77         nodes = array
 78         for i in stride(from: nodes.count / 2 - 1, through: 0, by: -1) {
 79             shiftDown(i)
 80         }
 81     }
 82     
 83     public mutating func reset() {
 84         for i in stride(from: nodes.count / 2 - 1, through: 0, by: -1) {
 85             shiftDown(i)
 86         }
 87     }
 88     
 89     @inline(__always) internal func parentIndex(ofIndex index: Int) -> Int {
 90         return (index - 1) / 2
 91     }
 92     
 93     @inline(__always) internal func leftChildIndex(ofIndex index: Int) -> Int {
 94         return index * 2 + 1
 95     }
 96     
 97     @inline(__always) internal func rightChildIndex(ofIndex index: Int) -> Int {
 98         return index * 2 + 2
 99     }
100     
101     public func peek() -> T? {
102         return nodes.first
103     }
104     
105     internal mutating func shiftUp(_ index: Int) {
106         var childIndex = index
107         let child = nodes[childIndex]
108         var parentIndex = self.parentIndex(ofIndex: index)
109         while childIndex > 0 && orderCriteria(child, nodes[parentIndex]) {
110             nodes[childIndex] = nodes[parentIndex]
111             childIndex = parentIndex
112             parentIndex = self.parentIndex(ofIndex: childIndex)
113         }
114         nodes[childIndex] = child
115     }
116     
117     internal mutating func shiftDown(from index: Int, until endIndex: Int) {
118         let leftChildIndex = self.leftChildIndex(ofIndex: index)
119         let rightChildIndex = self.rightChildIndex(ofIndex: index)
120         
121         var first = index
122         if leftChildIndex < endIndex && orderCriteria(nodes[leftChildIndex], nodes[first]) {
123             first = leftChildIndex
124         }
125         if rightChildIndex < endIndex && orderCriteria(nodes[rightChildIndex], nodes[first]) {
126             first = rightChildIndex
127         }
128         if first == index {
129             return
130         }
131         nodes.swapAt(index, first)
132         shiftDown(from: first, until: endIndex)
133     }
134     
135     internal mutating func shiftDown(_ index: Int) {
136         shiftDown(from: index, until: nodes.count)
137     }
138     
139     public mutating func insert(_ value: T) {
140         nodes.append(value)
141         shiftUp(nodes.count - 1)
142     }
143     
144     public mutating func insert<S: Sequence>(_ sequence:S) where S.Iterator.Element == T {
145         for value in sequence {
146             insert(value)
147         }
148     }
149     
150     public mutating func replace(index i: Int, value: T) {
151         guard i < nodes.count else {
152             return
153         }
154         remove(at: i)
155         insert(value)
156     }
157     
158     @discardableResult
159     public mutating func remove() -> T? {
160         guard !nodes.isEmpty else {
161             return nil
162         }
163         if nodes.count == 1 {
164             return nodes.removeLast()
165         } else {
166             let value = nodes[0]
167             nodes[0] = nodes.removeLast()
168             shiftDown(0)
169             return value
170         }
171     }
172     
173     @discardableResult
174     public mutating func remove(at index: Int) -> T? {
175         guard index < nodes.count else { return nil}
176         let size = nodes.count - 1
177         if index != size {
178             nodes.swapAt(index, size)
179             shiftDown(from: index,  until: size)
180             shiftUp(index)
181         }
182         return nodes.removeLast()
183     }
184     
185     public mutating func sort() -> [T] {
186         for i in stride(from: self.nodes.count - 1, to: 0, by: -1) {
187             nodes.swapAt(0, i)
188             shiftDown(from: 0, until: i)
189         }
190         return nodes
191     }
192 }

  1 class Solution {
  2     struct MinHeap<Element> where Element: Comparable {
  3         var values: [Element] = []
  4 
  5         func min() -> Element? {
  6             return values.first
  7         }
  8         mutating func insert(_ element: Element) {
  9             var current = values.count
 10             values.append(element)
 11 
 12             while current > 0 {
 13                 let parent = (current - 1) / 2
 14 
 15                 if values[parent] > values[current] {
 16                     values.swapAt(parent, current)
 17                     current = parent
 18                 } else {
 19                     break
 20                 }
 21             }
 22         }
 23 
 24         mutating func removeMin() {
 25             guard !values.isEmpty else {
 26                 return
 27             }
 28 
 29             let last = values.removeLast()
 30             guard !values.isEmpty else {
 31                 return
 32             }
 33             replaceMin(with: last)
 34         }
 35 
 36         mutating func replaceMin(with element: Element) {
 37             guard !values.isEmpty else {
 38                 values = [element]
 39                 return
 40             }
 41             values[0] = element
 42 
 43             var current = 0
 44             while true {
 45                 let leftIndex = current * 2 + 1
 46                 let rightIndex = current * 2 + 2
 47 
 48                 guard leftIndex < values.count else {
 49                     break
 50                 }
 51 
 52                 var child: Int
 53                 if rightIndex >= values.count || values[leftIndex] < values[rightIndex] {
 54                     child = leftIndex
 55                 } else {
 56                     child = rightIndex
 57                 }
 58 
 59                 if values[child] < values[current] {
 60                     values.swapAt(child, current)
 61                     current = child
 62                 } else {
 63                     break
 64                 }
 65             }
 66         }
 67     }
 68 
 69     struct Item: Comparable {
 70         var row, column: Int
 71         var height: Int
 72 
 73         static func <(_ lhs: Item, _ rhs: Item) -> Bool {
 74             return lhs.height < rhs.height
 75         }
 76 
 77         func validNeighbour(rowCount: Int, columnCount: Int) -> [(row: Int, column: Int)] {
 78             var result: [(row: Int, column: Int)] = []
 79             if row > 0 {
 80                 result.append((row - 1, column))
 81             }
 82             if row < rowCount - 1 {
 83                 result.append((row + 1, column))
 84             }
 85             if column > 0 {
 86                 result.append((row, column - 1))
 87             }
 88             if column < columnCount - 1 {
 89                 result.append((row, column + 1))
 90             }
 91 
 92             return result
 93         }
 94     }
 95 
 96     func trapRainWater(_ heightMap: [[Int]]) -> Int {
 97         let rowCount = heightMap.count, columnCount = heightMap.first?.count ?? 0
 98 
 99         guard rowCount > 2, columnCount > 2 else {
100             return 0
101         }
102 
103         var visited: [[Bool]] = Array(repeating: Array(repeating: false, count: columnCount), count: rowCount)
104         var boundaries = MinHeap<Item>()
105 
106         for row in 0..<rowCount {
107             visited[row][0] = true
108             visited[row][columnCount - 1] = true
109 
110             boundaries.insert(Item(row: row, column: 0, height: heightMap[row][0]))
111             boundaries.insert(Item(row: row, column: columnCount - 1, height: heightMap[row][columnCount - 1]))
112         }
113         for column in 1..<(columnCount - 1) {
114             visited[0][column] = true
115             visited[rowCount - 1][column] = true
116 
117             boundaries.insert(Item(row: 0, column: column, height: heightMap[0][column]))
118             boundaries.insert(Item(row: rowCount - 1, column: column, height: heightMap[rowCount - 1][column]))
119         }
120 
121         var total = 0
122         while let boundary = boundaries.min() {
123             boundaries.removeMin()
124             let boundaryHeight = boundary.height
125 
126             for (row, column) in boundary.validNeighbour(rowCount: rowCount, columnCount: columnCount) {
127                 guard !visited[row][column] else {
128                     continue
129                 }
130 
131                 let currentHeight = heightMap[row][column]
132                 let newHeight: Int
133 
134                 if currentHeight > boundaryHeight {
135                     newHeight = currentHeight
136                 } else {
137                     total += boundary.height - currentHeight
138                     newHeight = boundaryHeight
139                 }
140                 visited[row][column] = true
141 
142                 boundaries.insert(Item(row: row, column: column, height: newHeight))
143             }
144         }
145         return total
146     }
147 }
原文地址:https://www.cnblogs.com/strengthen/p/10329251.html