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
.
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!
有Stack和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
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; } }
类似题目:
[LeetCode] 11. Container With Most Water 装最多水的容器