Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it can trap after raining.

Solutions:
ans = sum {min(left_max,right_max)−height[i]min(left_max,right_max)−height[i] for all elements i} (竖)
= [min(height[current], height[st.top()]) - height[top]] * (current - st.top() - 1) (横)
(1) Brute Force
Time: O(n^2)
(2) Dynamic Programming
save left bar and right bar of each element i into an array
Time: O(n); Space: O(n)
C++:
int trap(vector<int>& height)
{
if(height == null)
return 0;
int ans = 0;
int size = height.size();
vector<int> left_max(size), right_max(size);
left_max[0] = height[0];
for (int i = 1; i < size; i++) {
left_max[i] = max(height[i], left_max[i - 1]);
}
right_max[size - 1] = height[size - 1];
for (int i = size - 2; i >= 0; i--) {
right_max[i] = max(height[i], right_max[i + 1]);
}
for (int i = 1; i < size - 1; i++) {
ans += min(left_max[i], right_max[i]) - height[i];
}
return ans;
}
// https://leetcode.com/problems/trapping-rain-water/solution/
(3) Stack: (calculate in one loop)
the left bar is in the stack after the top and right bar is the first one larger than top
the answer can be calculated in a horizontal way
Time: O(n); Space: O(n)
C++:
int trap(vector<int>& height)
{
int ans = 0, current = 0;
stack<int> st;
while (current < height.size()) {
while (!st.empty() && height[current] > height[st.top()]) {
int top = st.top();
st.pop();
if (st.empty())
break;
int distance = current - st.top() - 1;
int bounded_height = min(height[current], height[st.top()]) - height[top];
ans += distance * bounded_height;
}
st.push(current++);
}
return ans;
}
// https://leetcode.com/problems/trapping-rain-water/solution/
(4) 2 Pointers: (in one iteration)
the water trapped is dependant on the lower one of two side bars
so that if one side bar is larger, update the smaller one when it is lower than the current OR add to ans when larger than the current
Time: O(n); Space: O(1)
C++:
int trap(vector<int>& height)
{
int left = 0, right = height.size() - 1;
int ans = 0;
int left_max = 0, right_max = 0;
while (left < right) {
if (height[left] < height[right]) {
height[left] >= left_max ? (left_max = height[left]) : ans += (left_max - height[left]);
++left;
}
else {
height[right] >= right_max ? (right_max = height[right]) : ans += (right_max - height[right]);
--right;
}
}
return ans;
}
// https://leetcode.com/problems/trapping-rain-water/solution/
Java:
public int trap(int[] A){
int a=0;
int b=A.length-1;
int max=0;
int leftmax=0;
int rightmax=0;
while(a<=b){
leftmax=Math.max(leftmax,A[a]);
rightmax=Math.max(rightmax,A[b]);
if(leftmax<rightmax){
max+=(leftmax-A[a]); // leftmax is smaller than rightmax, so the (leftmax-A[a]) water can be stored
a++;
}
else{
max+=(rightmax-A[b]);
b--;
}
}
return max;
}
// https://leetcode.com/problems/trapping-rain-water/discuss/17391/Share-my-short-solution.
本文探讨了雨水捕捉问题的不同算法解决方案,包括暴力求解、动态规划、栈及双指针方法,并提供了详细的C++与Java实现代码。
632

被折叠的 条评论
为什么被折叠?



