Quantcast
Channel: 书影 - Entries for the tag leetcode
Viewing all articles
Browse latest Browse all 559

[LeetCode]Trapping Rain Water II

$
0
0

题目描述:

LeetCode 407. Trapping Rain Water II

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 are trapped between the blocks. The total volume of water trapped is 4.

题目大意:

给定一个m x n正整数矩阵,表示一个二维高程图,计算降雨后其中可以蓄积的雨量。

注意:

m和n值均小于110.每一个单元的高度在(0, 20000)之间。

解题思路:

BFS(广度优先搜索)

记矩形的高度、宽度分别为m, n,令二维数组peakMap[i][j] = ∞,表示矩形区域最多可以达到的水面高度

将矩形的四条边中的各点坐标加入队列q,并将各点对应的高度赋值给peakMap相同坐标

每次从q中弹出对头元素x, y,探索其上、下、左、右四个方向nx, ny:

尝试用max(peakMap[x][y], heightMap[nx][ny]) 更新 peakMap[nx][ny] 的当前值(取两者中的较小值)

Python代码:

class Solution(object):
    def trapRainWater(self, heightMap):
        """
        :type heightMap: List[List[int]]
        :rtype: int
        """
        m = len(heightMap)
        n = len(heightMap[0]) if m else 0

        peakMap = [[0x7FFFFFFF] * n for _ in range(m)]

        q = []

        for x in range(m):
            for y in range(n):
                if x in (0, m - 1) or y in (0, n - 1):
                    peakMap[x][y] = heightMap[x][y]
                    q.append((x, y))

        while q:
            x, y = q.pop(0)
            for dx, dy in zip((1, 0, -1, 0), (0, 1, 0, -1)):
                nx, ny = x + dx, y + dy
                if nx <= 0 or nx >= m - 1 or ny <= 0 or ny >= n - 1: continue
                limit = max(peakMap[x][y], heightMap[nx][ny])
                if peakMap[nx][ny] > limit:
                    peakMap[nx][ny] = limit
                    q.append((nx, ny))

        return sum(peakMap[x][y] - heightMap[x][y] for x in range(m) for y in range(n))

另外一种解法:

蓄积雨水的单元格存在两种情况:

1. 单元格的高度严格小于其上、下、左、右方向的4个单元格高度

2. 单元格的高度小于或等于其上、下、左、右方向的4个单元格高度

对于情况1,可以利用“木桶原理”将其高度调整为四周单元格中的最小高度

对于情况2,可以通过DFS,寻找与其邻接的等高节点的四周高度的最小值

Java代码:

public class Solution {

    private int m, n;
    private int[][] heightMap;
    private int dx[] = {1, 0, -1, 0};
    private int dy[] = {0, 1, 0, -1};

    private class Pair {
        public int x, y;
        public Pair(int x, int y) {
            this.x = x;
            this.y = y;
        }
        
        public int hashCode() {
            return x + y;
        }
        
        public boolean equals(Object o) {
            if (o instanceof Pair) {
                Pair p = (Pair)o;
                return x == p.x && y == p.y;
            }
            return false;
        }
    }
    public int trapRainWater(int[][] heightMap) {
        this.heightMap = heightMap;
        m = heightMap.length;
        n = m == 0 ? 0 : heightMap[0].length;
        int sum0 = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                sum0 += heightMap[i][j];
            }
        }
        LinkedList<Pair> queue = new LinkedList<Pair>();
        for (int i = 1; i < m - 1; i++) {
            for (int j = 1; j < n - 1; j++) {
                if (minNeighborHeight(i, j) >= heightMap[i][j]) {
                    queue.add(new Pair(i, j));
                }
            }
        }
        while (!queue.isEmpty()) {
            Pair head = queue.removeFirst();
            int i = head.x, j = head.y;
            HashSet<Pair> vs = new HashSet<Pair>();
            vs.add(head);
            int minh = solve(i, j, vs);

            if (minh > heightMap[i][j]) {
                queue.add(head);
                for (Pair e : vs) {
                    heightMap[e.x][e.y] = minh;
                }
            }
        }
        int sum1 = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                sum1 += heightMap[i][j];
            }
        }
        return sum1 - sum0;
    }
    private int minNeighborHeight(int i, int j) {
        int minh = Integer.MAX_VALUE;
        for (int k = 0; k < dx.length; k++) {
            int di = i + dx[k];
            int dj = j + dy[k];
            minh = Math.min(minh, heightMap[di][dj]);
        }
        return minh;
    }
    private int solve(int i, int j, HashSet<Pair> vs) {
        int height = heightMap[i][j];
        if (i == 0 || j == 0 || i == m - 1 || j == n - 1) {
            return height;
        }
        int minh = minNeighborHeight(i, j);
        if (minh != height) {
            return minh;
        }
        minh = Integer.MAX_VALUE;
        for (int k = 0; k < dx.length; k++) {
            int di = i + dx[k];
            int dj = j + dy[k];
            Pair pair = new Pair(di, dj);
            if (vs.contains(pair)) {
                continue;
            }
            if (heightMap[di][dj] == height) {
                vs.add(pair);
                minh = Math.min(minh, solve(di, dj, vs));
            } else {
                minh = Math.min(minh, heightMap[di][dj]);
            }
        }
        return minh;
    }
}

 


Viewing all articles
Browse latest Browse all 559

Trending Articles