42-Trapping Rain Water

Description:
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.

这里写图片描述

问题描述:
给定一个数组,数组元素为宽为1的柱的长,求出这个平面中的这个图形在下雨后能装的水的面积

例子:
输入 [0,1,0,2,1,0,1,3,2,1,2,1],返回6.

实际上,这题是Trapping Rain WaterII的前置题,不过因为我做的顺序是颠倒的,于是可以借用下II的思路。

解法1(最直观的套用II):

/*
可以看到,套路几乎没变,只是由立体变为了平面,可以选择的方向也只有两个,左和右(其实对于特定一个柱,只能往左或者右一个方向)
我们注意到,实际上从边缘的两个柱子开始,决定迭代顺序的决定性条件是两者的长,谁更长谁就先。
因此这也为我们解法2的优化提供了思路
*/
class Solution {
    private class Cell implements Comparable<Cell>{
        int index;
        int height;
        public Cell(int index, int height){
            this.index = index;
            this.height = height;
        }
        @Override
        public int compareTo(Cell cell1){
            return height - cell1.height;
        }
    }
    public int trap(int[] height) {
        if(height ==  null || height.length < 2)   return 0;

        int len = height.length;
        Queue<Cell> queue = new PriorityQueue<Cell>();
        boolean[] visited = new boolean[len];

        queue.offer(new Cell(0, height[0]));
        queue.offer(new Cell(len - 1, height[len - 1]));
        visited[0] = true;
        visited[len - 1] = true;

        int res = 0;
        while(!queue.isEmpty()){
            Cell cell = queue.poll();
            int i = cell.index + 1;
            if(i < len && !visited[i]){
                visited[i] = true;
                res += Math.max(0, cell.height - height[i]);
                queue.offer(new Cell(i, Math.max(height[i], cell.height)));
            }
            int j = cell.index - 1;
            if(j >= 0 && !visited[j]){
                visited[j] = true;
                res += Math.max(0, cell.height - height[j]);
                queue.offer(new Cell(j, Math.max(height[j], cell.height)));
            }
        }

        return res;
    }
}

解法2(two pointers):

/*
我为了追求与II的连贯,也为了更加清晰直观,因此保留了Cell。
注意到,这个解法已经没有优先级队列了。
*/
class Solution {
    private class Cell implements Comparable<Cell>{
        int index;
        int height;
        public Cell(int index, int height){
            this.index = index;
            this.height = height;
        }
        @Override
        public int compareTo(Cell cell1){
            return height - cell1.height;
        }
    }
    public int trap(int[] height) {
        if(height ==  null || height.length < 2)   return 0;

        int len = height.length;
        Cell left = new Cell(0, height[0]), right = new Cell(len - 1, height[len - 1]);

        int res = 0;
        while(left.index < right.index){
        //注意这里,长度决定了处理的先后顺序,内部的运算与II别无二致
            if(left.height < right.height){
                int i = left.index + 1;
                res += Math.max(0, left.height - height[i]);
                left.index = i;
                left.height = Math.max(left.height, height[i]);
            }else{
                int i = right.index - 1;
                res += Math.max(0, right.height - height[i]);
                right.index = i;
                right.height = Math.max(right.height, height[i]);
            }
        }

        return res;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值