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!
这个问题可以转化为统计水的小方块的个数。左右双指针从两边往中间走,找到较高的一边,从较低的一边倒水。如果左比右小,看这一刻的高度是不是在左边有比他高的边,有的话加上左边最高的边与这一刻边的差,没有的话,说明这一刻的边是左边最高,记录下来;右边比左边小的情况同理。代码如下:public class Solution {
public int trap(int[] height) {
int left = 0, right = height.length - 1;
int leftMax = 0, rightMax = 0;
int res = 0;
while (left < right) {
if (height[left] <= height[right]) {
if (height[left] > leftMax) {
leftMax = height[left];
} else {
res += (leftMax - height[left]);
}
left ++;
} else {
if (height[right] > rightMax) {
rightMax = height[right];
} else {
res += (rightMax - height[right]);
}
right --;
}
}
return res;
}
}
另一种方法,先从左到右遍历,记录左边的最高点,在从右向左遍历,记录右边的最高点,最后从左到右遍历,如果当前的高度在左右都有比他高的遍,加上左右高度较小的与此刻高度的差,如果当前的高度在左右没有比他高的边或者只有一个比他高的边,说明这一列没法装水,跳过。代码如下:
public class Solution {
public int trap(int[] height) {
//corner case
if (height == null || height.length == 0) return 0;
int len = height.length;
int[] left = new int[len];
int[] right = new int[len];
int sum = 0;
left[0] = 0;
right[len - 1] = height[len - 1];
for (int i = 1; i < len; i++) {
left[i] = Math.max(left[i - 1], height[i - 1]);
}
for (int i = len - 2; i >= 0; i--) {
right[i] = Math.max(right[i + 1], height[i + 1]);
}
for (int i = 0; i < len; i++) {
if (Math.min(left[i], right[i]) <= height[i]) {
sum += 0;
} else {
sum += Math.min(left[i], right[i]) - height[i];
}
}
return sum;
}
}