[LeetCode] 42. 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.


The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped. Thanks Marcos for contributing this image!

Example:

Input: [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6

解法1:双指针Two Pointers,left和right分别指向数组的头尾,从两边向中间扫描,在当前两指针的范围内,先比较两头找出较小值,如果较小值是left指向的值,则从左向右扫描,如果较小值是right指向的值,则从右向左扫描,若遇到的值比当较小值小,则将差值存入结果,如遇到的值大,则重新确定新的窗口范围,迭代直至left和right指针重合。

对于任何一个坐标,检查其左右的最大坐标,然后相减就是容积。所以, 
1. 从左往右扫描一遍,对于每一个坐标,求取左边最大值。
2. 从右往左扫描一遍,对于每一个坐标,求最大右值。
3. 再扫描一遍,求取容积并加和。
2和3可以合并成一个循环,公式:H[i] = min(Max(Array[j] ),  Max(Array[k])) – Array[i]  where  j < i and k > i

解法2:栈stack

Follow up:

不求所有容积,而是求容积中的最大值。这样就类似于Container With Most Water,但是有不同的地方,这题里面每一个坐标本身是占体积的。所以从两边往中间扫的时候,根本不知道中间坐标共占用了多少体积。

Java:

public class Solution {
    public int trapRainWater(int[] heights) {
        if (heights.length == 0) {
            return 0;
        }
        
        int[] maxHeights = new int[heights.length + 1];
        maxHeights[0] = 0;
        for (int i = 0; i < heights.length; i++) {
            maxHeights[i + 1] = Math.max(maxHeights[i], heights[i]);
        }
        
        int max = 0, area = 0;
        for (int i = heights.length - 1; i >= 0; i--) {
            area += Math.min(max, maxHeights[i]) > heights[i]
                    ? Math.min(max, maxHeights[i]) - heights[i]
                    : 0;
            max = Math.max(max, heights[i]);
        }
        
        return area;
    }
}

Java: 参考

public class Solution {
    public int trap(int[] height) {
        Stack<Integer> st = new Stack<Integer>();
        if(height.length == 0)
            return 0;
        int i = 0;
        int j = height.length - 1;
        int ans = 0;//返回的答案
        int secHight = 0;//第二个高度(最高的那个不动)
        while(i < j){
            if(height[i] < height[j]){
                secHight = Math.max(secHight,height[i]);
                //因为长度为1,高度也就是面积值,如果height[i]==secHight,则新增面积为0
                ans += secHight - height[i];
                i++;
            }else{
                secHight = Math.max(secHight,height[j]);
                //因为长度为1,高度也就是面积值,如果height[i]==secHight,则新增面积为0
                ans += secHight - height[j];
                j--;
            }
        }
        return ans;
    }
}  

Python:

class Solution:
    # @param A, a list of integers
    # @return an integer
    def trap(self, A):
        result = 0
        top = 0
        for i in xrange(len(A)):
            if A[top] < A[i]:
                top = i

        second_top = 0
        for i in xrange(top):
            if A[second_top] < A[i]:
                second_top = i
            result += A[second_top] - A[i]

        second_top = len(A) - 1
        for i in reversed(xrange(top, len(A))):
            if A[second_top] < A[i]:
                second_top = i
            result += A[second_top] - A[i]

        return result

Python:

# Time:  O(n)
# Space: O(n)
class Solution2:
    # @param A, a list of integers
    # @return an integer
    def trap(self, A):
        result = 0
        stack = []

        for i in xrange(len(A)):
            mid_height = 0
            while stack:
                [pos, height] = stack.pop()
                result += (min(height, A[i]) - mid_height) * (i - pos - 1)
                mid_height = height

                if A[i] < height:
                    stack.append([pos, height])
                    break
            stack.append([i, A[i]])

        return result

Python: wo

class Solution(object):
    def trap(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        if not height:
            return 0
        res = 0
        left, right = 0, len(height) - 1
        left_max, right_max = 0, 0
        while left < right:
            if height[left] < height[right]:
                left_max = max(left_max, height[left])
                left += 1
                res += max(0, left_max - height[left])
            else:
                right_max = max(right_max, height[right])
                right -= 1
                res += max(0, right_max - height[right])
                
        return res    

C++:

// Time:  O(n)
// Space: O(1)
class Solution {
public:
    int trap(vector<int>& height) {
        if (height.empty()) {
            return 0;
        }

        int i = 0, j = height.size() - 1;
        int left_height = height[0];
        int right_height = height[height.size() - 1];
        int trap = 0;

        while (i < j) {
            if (left_height < right_height) {
                ++i;
                // Fill in the gap.
                trap += max(0, left_height - height[i]);
                // Update current max height from left.
                left_height = max(left_height, height[i]);
            }
            else {
                --j;
                // Fill in the gap.
                trap += max(0, right_height - height[j]);
                // Update current max height from right.
                right_height = max(right_height, height[j]);
            }
        }

        return trap;
    }
};

C++:

int trap(vector<int>& height) {
    int l = 0, r = height.size()-1, level = 0, water = 0;
    while (l < r) {
        int lower = height[height[l] < height[r] ? l++ : r--];
        level = max(level, lower);
        water += level - lower;
    }
    return water;
}

C++:

#include <bits/stdc++.h>
 
using namespace std;
 
// two pointers
class Solution {
public:
    int trap(vector<int>& height) {
        int n = height.size();
		// Exceptional Case: 
		if(n <= 2){
			return 0;
		}
		int ans = 0;
		int left = 0, right = n - 1;
		while(left < right){
			int min_height = min(height[left], height[right]);
			if(height[left] == min_height){
				while(++left < right && height[left] <= min_height){
					ans += (min_height - height[left]);
				}
			}
			else if(height[right] == min_height){
				while(left < --right && height[right] <= min_height){
					ans += (min_height - height[right]);
				}
			}
		}
		return ans;
    }
};

  

    

 

类似题目:

[LeetCode] 11. Container With Most Water 装最多水的容器

[LeetCode] 407. Trapping Rain Water II 收集雨水 II

 

All LeetCode Questions List 题目汇总

 

 

 

 

 

 

转载于:https://www.cnblogs.com/lightwindy/p/8495692.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值