[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
的矩阵,其中的值均为正整数,代表二维高度图每个单元的高度,请计算图中形状最多能接多少体积的雨水。
说明:
m 和 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。
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 }
18952 kb
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 }