LeetCode42. 接雨水
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
示例 1:
输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。
示例 2:
输入:height = [4,2,0,3,2,5]
输出:9
提示:
n == height.length
0 <= n <= 3 * 104
0 <= height[i] <= 105
一、暴力破解
class Solution {
//暴力解法
public int trap(int[] height) {
int n=height.length;
int ans=0;
for(int i=1;i<n-1;i++){
int l_max=0,r_max=0;
//找出左边最高的
for(int j=i;j>=0;j--){
l_max=Math.max(l_max,height[j]);
}
//找出右边最高的
for(int j=i;j<n;j++){
r_max=Math.max(r_max,height[j]);
}
ans+=Math.min(l_max,r_max)-height[i];
}
return ans;
}
}
二、动态规划
class Solution {
public int trap(int[] height) {
int n=height.length;
if(n==0) return 0;
int[] left_max=new int[n];
int[] right_max=new int[n];
left_max[0]=height[0];
right_max[n-1]=height[n-1];
//left_max表示该坐标左边最大的整数
for(int i=1;i<n;i++){
left_max[i]=Math.max(left_max[i-1],height[i]);
}
//right_max表示该坐标右边最大的整数
for(int i=n-2;i>=0;i--){
right_max[i]=Math.max(right_max[i+1],height[i]);
}
int ans=0;
for(int i=1;i<n;i++){
ans+=Math.min(left_max[i],right_max[i])-height[i];
}
return ans;
}
}
三、双指针法
class Solution {
public int trap(int[] height) {
int ans=0;
int left=0,right=height.length-1;
int leftMax=0,rightMax=0;
while(left < right){
leftMax=Math.max(leftMax,height[left]);
rightMax=Math.max(rightMax,height[right]);
if(height[left] < height[right]){
ans+=leftMax-height[left];
left++;
}else{
ans+=rightMax-height[right];
right--;
}
}
return ans;
}
}
四、单调栈
class Solution {
public int trap(int[] height) {
if(height.length==0) return 0;
Stack<Integer> stack=new Stack<>();
int ans=0;
for(int i=0;i<height.length;i++){
while(!stack.isEmpty() && height[i] > height[stack.peek()]){
int cur=stack.pop();
if(stack.isEmpty()) break;
int left=stack.peek();
int right=i;
int width=right-left-1;
int cheight=Math.min(height[left],height[i])-height[cur];
ans+=cheight*width;
}
stack.push(i);
}
return ans;
}
}