• 【LeetCode】接雨水 II [H](堆)


    407. 接雨水 II - 力扣(LeetCode)

    一、题目

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

    示例 1:

    输入: heightMap = [[1,4,3,1,3,2],[3,2,1,3,2,4],[2,3,3,2,3,1]]
    输出: 4
    解释: 下雨后,雨水将会被上图蓝色的方块中。总的接雨水量为1+2+1=4。 

    示例 2:

    输入: heightMap = [[3,3,3,3,3],[3,2,2,2,3],[3,2,1,2,3],[3,2,2,2,3],[3,3,3,3,3]]
    输出: 10 

    提示:

    • m == heightMap.length
    • n == heightMap[i].length
    • 1 <= m, n <= 200
    • 0 <= heightMap[i][j] <= 2 * 104

    二、代码

    1. class Solution {
    2. class Node {
    3. // 坐标
    4. public int x;
    5. public int y;
    6. // 该位置的的高度
    7. public int value;
    8. public Node(int x, int y, int value) {
    9. this.x = x;
    10. this.y = y;
    11. this.value = value;
    12. }
    13. }
    14. public int trapRainWater(int[][] heightMap) {
    15. // 小根堆
    16. PriorityQueue heap = new PriorityQueue<>((a, b) -> a.value - b.value);
    17. // 矩阵的行数
    18. int n = heightMap.length;
    19. // 矩阵的列数
    20. int m = heightMap[0].length;
    21. // 内弧的瓶颈
    22. int max = 0;
    23. // 标志当前位置是否已经加入到过小根堆,true表示已经加入过小根堆
    24. boolean[][] isVisited = new boolean[n][m];
    25. // 先将矩阵的四周的都加入到堆中,四周一定是存不下水的
    26. for (int i = 0; i < m; i++) {
    27. heap.add(new Node(0, i, heightMap[0][i]));
    28. isVisited[0][i] = true;
    29. }
    30. for (int i = 1; i < n; i++) {
    31. heap.add(new Node(i, m - 1, heightMap[i][m - 1]));
    32. isVisited[i][m - 1] = true;
    33. }
    34. for (int i = m - 2; i >= 0; i--) {
    35. heap.add(new Node(n - 1, i, heightMap[n - 1][i]));
    36. isVisited[n - 1][i] = true;
    37. }
    38. for (int i = n - 2; i >= 1; i--) {
    39. heap.add(new Node(i, 0, heightMap[i][0]));
    40. isVisited[i][0] = true;
    41. }
    42. // 记录总的水量
    43. int water = 0;
    44. while (!heap.isEmpty()) {
    45. // 将堆顶弹出
    46. Node cur = heap.poll();
    47. int row = cur.x;
    48. int col = cur.y;
    49. // 用堆顶尝试更新瓶颈Max
    50. max = Math.max(max, cur.value);
    51. // 将弹出位置的上、下、左、右还没有加入过堆的位置加入到堆中,同时结算加入堆的位置的水量
    52. if (row > 0 && !isVisited[row - 1][col]) {
    53. heap.add(new Node(row - 1, col, heightMap[row - 1][col]));
    54. isVisited[row - 1][col] = true;
    55. water += (Math.max(0, max - heightMap[row - 1][col]));
    56. }
    57. if (row < n - 1 && !isVisited[row + 1][col]) {
    58. heap.add(new Node(row + 1, col, heightMap[row + 1][col]));
    59. isVisited[row + 1][col] = true;
    60. water += (Math.max(0, max - heightMap[row + 1][col]));
    61. }
    62. if (col > 0 && !isVisited[row][col - 1]) {
    63. heap.add(new Node(row, col - 1, heightMap[row][col - 1]));
    64. isVisited[row][col - 1] = true;
    65. water += (Math.max(0, max - heightMap[row][col - 1]));
    66. }
    67. if (col < m - 1 && !isVisited[row][col + 1]) {
    68. heap.add(new Node(row, col + 1, heightMap[row][col + 1]));
    69. isVisited[row][col + 1] = true;
    70. water += (Math.max(0, max - heightMap[row][col + 1]));
    71. }
    72. }
    73. // 返回总水量
    74. return water;
    75. }
    76. }

    三、解题思路 

    整个流程就还是按照求瓶颈的思想来结算水量,具体的流程在代码注释中。

    用堆的作用就是保证从小到大开始处理,这样能将max内弧中的数全都结算完水量(该内弧中所有小于max的数),再去更新更大的max,去结算新的内弧水量,避免数据遗漏。

    如果此时小根堆里最小值都超过max了,那么说明此时小根堆里的所有值都超过max了,也就是此时已经来到了一个全新的内弧了,不再是以前那个max作为瓶颈的内弧了,现在遍历来到了一个全新的内弧。

  • 相关阅读:
    Linux之Python-APT 软件管理和远程登录
    jupyter notebook的安装和使用
    【Java 基础篇】Java 实现模拟斗地主游戏
    upp(统一流程平台),一份迟来的可行性研究报告
    Mac/Wins Matlab如何查看APPs源码
    JAVA毕业设计web大学生宿舍管理系统计算机源码+lw文档+系统+调试部署+数据库
    Canal使用和安装总结
    lua变量、数据类型、if判断条件和数据结构table以及【lua 函数】
    【视觉基础篇】10 # 图形系统如何表示颜色?
    洛谷 模板汇总 算法基础 python解析
  • 原文地址:https://blog.csdn.net/cy973071263/article/details/128082442