给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 感谢 Marcos 贡献此图。
示例:
输入: [0,1,0,2,1,0,1,3,2,1,2,1] 输出: 6
方法一(运行超时):
思路:按层数统计 每层遍历 O(n3)
class Solution {
// 思路:按层数统计 每层遍历 从第一个大于等于k的开始 从下一个大于等于k的结束
public int trap(int[] height) {
// 判空
if(height.length==0) return 0;
// 先取出数组的最大值和最小值
int max=height[0];
int min=height[0];
for(int i=0;i<height.length;i++){
max=height[i]>max?height[i]:max;
min=height[i]>min?min:height[i];
}
int sum=0;
for(int i=min+1;i<=max;i++){
int pre=-1;
int next=-1;
for(int index=0;index<height.length;index++){
if(height[index]>=i && pre==-1){
pre=index;
next=pre;
}
if(height[index]>=i && pre!=-1){
next=index;
}
}
for(int j=pre+1;j<next;j++){
if(height[j]<i){
height[j]+=1;
sum+=1;
}
}
}
return sum;
}
}
方法二:
思路:木桶原理 乘多少水由最小值决定 从两边往中间搜索(实质是向最大值靠近 分为左右两边分别统计) O(n)
class Solution {
// 思路:木桶原理 乘多少水由最小值决定 从两边往中间搜索(实质是向最大值靠近 分为左右两边分别统计)
public int trap(int[] height) {
// 判空
if(height.length==0) return 0;
// 左右向中间搜索
int left=0;
int right=height.length-1;
int sum=0;
// 保存局部最大值
int secHeight=0;
while(left<right){
if(height[left]<height[right]){
secHeight=secHeight>height[left]?secHeight:height[left];
sum+=secHeight-height[left];
left++;
}
else{
secHeight=secHeight>height[right]?secHeight:height[right];
sum+=secHeight-height[right];
right--;
}
}
return sum;
}
}