题目描述
给定 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
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/trapping-rain-water
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
暴力
时间复杂度 O(n^2)
空间复杂度 O(1)
class Solution {
public int trap(int[] height) {
int len = height.length;
int res =0;
for(int i=0;i<len;i++){
int maxLeft =0;
int maxRight =0;
//左右的取值会影响累加的结果
int left=i, right=i;
while(left>=0){
maxLeft = Math.max(maxLeft,height[left]);
left--;
}
while(right<len){
maxRight = Math.max(maxRight,height[right]);
right++;
}
res += (Math.min(maxRight,maxLeft) - height[i] );
}
return res;
}
}
优化暴力
时间复杂度 O(n)
空间复杂度 O(n)
class Solution {
public int trap(int[] height) {
int len = height.length;
int res =0;
int[] maxLeft = new int[len];
int[] maxRight = new int[len];
int leftmax=0,rightmax =0;
for(int i=0;i<len;i++){
leftmax = Math.max(leftmax,height[i]);
maxLeft[i] = leftmax;
}
for(int i=len-1;i>=0;i--){
rightmax = Math.max(rightmax,height[i]);
maxRight[i] = rightmax;
}
for(int i=0;i<len;i++){
res += Math.min(maxLeft[i],maxRight[i]) - height[i];
}
return res;
}
}
双指针
时间复杂度 O(n)
空间复杂度 O(1)
class Solution {
public int trap(int[] height) {
int p1=0;
int p2 = height.length-1;
int maxright = 0;
int maxleft = 0;
int res=0;
while(p1<p2){
if(height[p1]<height[p2]){
maxright = Math.max(maxright,height[p1]);
res += maxright -height[p1];
p1++;
}else{
maxleft = Math.max(maxleft,height[p2]);
res += maxleft - height[p2];
p2--;
}
}
return res;
}
}
栈
时间复杂度 O(n)
空间复杂度 O(n)
Stack()类 运行起来 没有Deque(LinkedList)快
class Solution {
public int trap(int[] height) {
int len = height.length;
if(len<2) return 0;
int res=0, i=0;
// Stack<Integer> stack = new Stack<>();
Deque<Integer> stack = new LinkedList<Integer>();
while(i<len){
while(!stack.isEmpty() && height[i]>height[stack.peek()]){
int mid = stack.pop();
if(stack.isEmpty()) break;
int left = stack.peek();
int distance = i-left-1;
res += (distance * (Math.min(height[left],height[i])-height[mid]));
}
stack.push(i);
i++;
}
return res;
}
}