Leetcode 407. Trapping Rain Water II

来源:互联网 发布:c语言需要掌握 编辑:程序博客网 时间:2024/05/29 18:46

题目:

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.

思路:

在本题之前,有一个比较简单的题Trapping Rain Water,题目是:

Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.

For example,
Given [0,1,0,2,1,0,1,3,2,1,2,1], return 6.

解这个题时,要用到动态规划。具体思路是:分别从左右两边向中间寻找,左边最高leftMax与右边最高rightMax先初始化为0,然后左右分别与对应的最高比较,并更新leftMax与rightMax的值。如果leftMax<rightMax,根据木桶原理,装多少水由左边决定,如果left对应位置比左边最高小,说明它能装水;否则,装不了水,并更新leftMax的值。leftMax>=rightMax时情况类似,直到left=right时说明查找完毕。具体代码如下:

C++实现

class Solution {public:    int trap(vector<int>& height) {        int left = 0, right = height.size() - 1, leftMax = 0, rightMax = 0, result = 0;        while (left < right) {            leftMax = max(height[left], leftMax);            rightMax = max(height[right], rightMax);            if (leftMax < rightMax) {                result += leftMax - height[left++];            }            else {                result += rightMax - height[right--];            }        }        return result;    }};

在这个题中,维度由二维变成了三维,但基本思路不变。首先将四周的元素装入一个优先队列,并标记为已访问。然后取出一个最矮的,并在队列中删除,然后用此值与最高值比较并更新最高值。之后将取出的这个元素与其上下左右的元素进行比较,并将四个值标记为已访问并放入队列中。如果那四个元素中有比此元素矮的,则表明它可以存水。(之后出队列的即使比前一个更矮也没事,因为它不能改变最高值)。直到优先队列中的所有元素出队后结束。

代码:

C++实现

class H {public:    int height;    int x;    int y;};bool operator>(const H& n1, const H& n2) {    return n1.height > n2.height;}class Solution {public:    int trapRainWater(vector<vector<int>>& heightMap) {        int maxh = 0;        int result = 0;        int m = heightMap.size();        if (m == 0) return 0;        int n = heightMap[0].size();        if (n == 0) return 0;        vector<vector<int>> visited(m, vector<int>(n, 0));        priority_queue<H, vector<H>, greater<H> > que;        for (int i = 0; i < m; i ++) {            for (int j = 0; j < n; j ++){                if (!(i == 0 || i == m - 1 || j == 0 || j == n - 1)) continue;                H h;                h.height = heightMap[i][j];                h.x = i;                h.y = j;                que.push(h);                visited[i][j] = 1;            }        }        vector<vector<int>> dir{{1, 0}, {-1, 0}, {0, 1}, {0, -1}};        while (!que.empty()) {            H val = que.top();            que.pop();            int tall = val.height, row = val.x, col = val.y;            maxh = max(maxh, tall);            for(auto d: dir) {                int row1 = row + d[0], col1 = col + d[1];                if(row1 >= m || row1 < 0 || col1 < 0 || col1 >= n || visited[row1][col1]) continue;                visited[row1][col1] = 1;                if (heightMap[row1][col1] < maxh) result += (maxh - heightMap[row1][col1]);                H h;                h.height = heightMap[row1][col1];                h.x = row1;                h.y = col1;                que.push(h);            }        }        return result;    }};

本题中令我收获最大的是以下的代码块:

class H {public:    int height;    int x;    int y;};bool operator>(const H& n1, const H& n2) {    return n1.height > n2.height;}class H { public:     H(int a, int b, int c):height(a),x(b),y(c){}     int height;     int x;     int y;     bool operator>(const H& n1) const {         return height > n1.height;     } };
即如果需要定义新的数据类型时,可以使用class!当然,class中的方法和属性默认是private的,所以需要在前面加上public来让外部访问。

另外,下面H的构造函数也值得一看,这样构造可以省去好多代码,但意义是一样的。

还有>运算符重载,此处必须重载,不然priority_queue中的greater没法用!可看出,重载也有两种方法,但是下面那个重载函数的格式并没有很看懂,暂且先记住这种实现方式吧!


0 0
原创粉丝点击