leetcode_51 Trapping Rain Water II

161 篇文章 0 订阅

题目:

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.

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.

理论分析:

 Min Heap
- 用PriorityQueue把选中的height排序,为走位, create class Cell (x,y, height).

注意几个理论
- 1. 从matrix四周开始考虑,发现matrix能Hold住的水,取决于height低的block
- 2. 必须从外围开始考虑,因为水是被包裹在里面,外面至少需要现有一层
- 以上两点就促使我们用min-heap: 也就是natural order的PriorityQueue<Cell>.

 Steps
- 1. process的时候,画个图也可以搞清楚: 就是四个方向都走走,用curr cell的高度减去周围cell的高度.
- 2. 若大于零,那么周围的cell就有积水: 因为cell已经是外围最低, 所以内部更低的, 一定有积水.
- 3. 每个visited的cell都要mark, avoid revisit
- 4. 根据4个方向的走位 `(mX, mY)` 创建新cell 加进queue里面: cell(mX, mY) 已经计算过积水后, 外围墙小时, `(mX, mY)`就会变成墙.
- 5. 因为做的是缩小一圈的新围墙, height = Math.max(cell.h, neighbor.h);
- 和trapping water I 想法一样。刚刚从外围,只是能加到跟外围cell高度一致的水平面。往里面,很可能cell高度变化。   
- 这里要附上curr cell 和 move-to cell的最大高度。

为什么想到用Heap (min-heap - priorityQueue)
- 要找到bucket的最短板
- 每次需要最先处理最短的那条 (on top)

为什么从外向里遍历
- 木桶理论, 包水, 是从外面包住里面
- 洋葱剥皮, 用完丢掉

class Solution {
public:
    class cell{
    public:
        int x;
        int y;
        int h;
        cell(int x,int y, int h)
        {
            this->x = x;
            this->y = y;
            this->h = h;
        }
    };
    struct comp{
      bool operator()(const cell &c1, const cell &c2)
      {
          return c1.h > c2.h;
      }
    };
    int trapRainWater(vector<vector<int>>& heightMap) {
        if(heightMap.size() == 0 || heightMap[0].size() == 0)
             return 0;
        int total = 0;
        priority_queue<cell,vector<cell>,comp> que;
        
        int m = heightMap.size();
        int n = heightMap[0].size();
        bool visited[110][110];
        memset(visited,false,110*110);
        for(int i = 0; i < m; i++)
        {
            visited[i][0] = true;
            visited[i][n-1] = true;
            que.push(cell(i,0,heightMap[i][0]));
            que.push(cell(i,n-1,heightMap[i][n-1]));
        }
        
        for(int j = 0; j < n; j++)
        {
            visited[0][j] = true;
            visited[m-1][j] = true;
            que.push(cell(0,j,heightMap[0][j]));
            que.push(cell(m-1,j,heightMap[m-1][j]));
        }
        
        int dx[] = {0,0,1,-1};
        int dy[] = {1,-1,0,0};
        
        while(!que.empty()){
            cell c = que.top();
            que.pop();
            for(int i = 0; i < 4; i++){
                int mx = c.x + dx[i];
                int my = c.y + dy[i];
                if(mx >= 0 && mx < m && my >= 0 && my < n && !visited[mx][my])
                {
                    visited[mx][my] = true;
                    if(c.h > heightMap[mx][my])
                    {
                        total += c.h - heightMap[mx][my];
                    }
                    que.push(cell(mx,my,max(c.h,heightMap[mx][my])));
                }
            }
        }
       return total; 
    }
};

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值