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.
Solution 1:dynamic programming
- For each h in height, find the largest height to its left and the largest height to its right.
- For each h, if h is less than the smaller height of its two sides, add the height difference to the result.
Time Complexity: O(n), space complexity: O(n)
class Solution {
public int trap(int[] height) {
if(height == null || height.length == 0)
return 0;
int[] left = new int[height.length];
left[0] = height[0];
for(int i = 1; i < height.length; i++) {
left[i] = Math.max(left[i-1], height[i]);
}
int[] right = new int[height.length];
right[height.length-1] = height[height.length-1];
for(int i = height.length-2; i >= 0; i--) {
right[i] = Math.max(right[i+1], height[i]);
}
int res = 0;
for(int i = 1; i < height.length-1; i++) {
int h = Math.min(left[i], right[i]);
if(h > height[i]) {
res+=h-height[i];
}
}
return res;
}
}
Solution 2: Similar to solution 1, but use two pointers so as to reduce the looping times
Time Complexity: O(n), space Complexity: O(1)
class Solution {
public int trap(int[] height) {
if(height == null || height.length == 0)
return 0;
int left = 0;
int right = height.length-1;
int left_max = 0;
int right_max = 0;
int res = 0;
while(left < right) {
if(height[left] < height[right]) {
if(height[left] >= left_max)
left_max = height[left];
else
res += left_max-height[left];
++left;
} else {
if(height[right] >= right_max)
right_max = height[right];
else
res += right_max-height[right];
--right;
}
}
return res;
}
}
Solution 3: a simpler version of solution 2
Time complexity: O(n), space complexity: O(1)
class Solution {
public int trap(int[] height) {
int l = 0, r = height.length - 1, level = 0, res = 0;
while (l < r) {
int lower = height[(height[l] < height[r]) ? l++ : r--];
level = Math.max(level, lower);
res += level - lower;
}
return res;
}
}
Solution 4: use stack (last in first out)
- Use stack to store indices
- For each iteration,
(1) If the stack is empty or the current height <= height at the top of the stack, push the current index to stack.
(2)Otherwise, pop the top index from the stack. If stack is empty, there are no water to be trapped. If stack is not empty, the water is trapped by the height which is min(current height, height of the top index of the stack), and the width is (current index - top index in the stack -1.)
class Solution {
public int trap(int[] height) {
Stack<Integer> s = new Stack();
int res = 0;
for(int i = 0; i < height.length; ) {
if(s.isEmpty() || height[i] <= height[s.peek()])
s.push(i++);
else {
int t = s.pop();
if(s.isEmpty())
continue;
res += (Math.min(height[s.peek()], height[i])-height[t])*(i-s.peek()-1);
}
}
return res;
}
}
Reference