Problem
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]
, return6
.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.
Solution
用两个数组,维护从左边到当前的元素最大高度,另外一个是从右边到当前元素的最大高度。当前元素的积水高度就取决于左右两边的较小值 - 当前元素高度。
Swift
class Solution {
func trap(height: [Int]) -> Int {
if height.count == 0 {
return 0
}
var leftMax: [Int] = []
var rightMax: [Int] = []
var maxH = -1
for h in height {
leftMax.append(maxH)
maxH = max(maxH, h)
}
maxH = -1
for h in height.reverse() {
rightMax.insert(maxH, atIndex: 0)
maxH = max(maxH, h)
}
var ret : Int = 0
for i in 0..<leftMax.count {
let h = min(leftMax[i], rightMax[i])
let water = max(0, h - height[i])
ret += water
}
return ret
}
}
另一种思路:Time: O(n)
, Space: O(1)
维护左右两个指针,然后朝里推进。于此同时,维护左右两边的最大高度。如果左边的较小,左边指针向右推进,然后根据左右两边最小的高度确定当前格子可以存多少水。这里的关键是,将左右两边更小的那个指针向里推进,有点像非递减序列地去填水。
Swift
class Solution {
func trap(height: [Int]) -> Int {
if height.count == 0 {
return 0
}
var i = 0
var j = height.count - 1
var ret = 0
var leftHeight = height[0]
var rightHeight = height[j]
while i < j {
let minHeight = min(leftHeight, rightHeight)
if (leftHeight < rightHeight) {
i += 1
let water = max(minHeight - height[i], 0)
ret += water
leftHeight = max(leftHeight, height[i])
} else {
j -= 1
let water = max(minHeight - height[j], 0)
ret += water
rightHeight = max(rightHeight, height[i])
}
}
return ret
}
}
C++
class Solution {
public:
/**
* @param heights: a vector of integers
* @return: a integer
*/
int trapRainWater(vector<int> &heights) {
if (heights.size() == 0) {
return 0;
}
int i = 0;
int j = heights.size() - 1;
int leftHeight = heights[i];
int rightHeight = heights[j];
int ret = 0;
while (i < j) {
int minHeight = min(leftHeight, rightHeight);
if (leftHeight < rightHeight) {
i++;
int water = max(minHeight - heights[i], 0);
ret += water;
leftHeight = max(leftHeight, heights[i]);
} else {
j--;
int water = max(minHeight - heights[j], 0);
ret += water;
rightHeight = max(rightHeight, heights[j]);
}
}
return ret;
}
};