zoukankan      html  css  js  c++  java
  • [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 }
  • 相关阅读:
    java 接口返回格式
    Request must contain an kbn-xsrf header 报错
    java 类型转换
    layui中使用ajax请求后端
    string boot中get、post 接口
    mysql window 启动
    自动化--APP UI自动化--Airtest 实用命令汇总
    自动化--APP UI自动化--Airtest poco定位
    自动化--APP UI自动化--Airtest点击悬浮
    最近工作
  • 原文地址:https://www.cnblogs.com/strengthen/p/10329251.html
Copyright © 2011-2022 走看看