这是我参与8月更文挑战的第14天,活动详情查看:8月更文挑战
42. 接雨水
给定 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
解题思路
-
维护一个单调栈,单调栈内的元素是递减的,当前遍历的元素如果大于栈顶的元素,有因为栈是单调递减的,所以栈顶元素的前面存在更大的元素,因此就可以形成一个接雨水的区域了。
-
接雨水的宽度由左右两个元素的下标差决定,而高度由左右两边较小的那个元素和栈顶元素决定
遍历所有高度:
-
当前高度小于等于栈顶高度,入栈,指针后移。
-
当前高度大于栈顶高度,出栈,计算出当前墙和栈顶的墙之间水的多少,然后计算当前的高度和新栈的高度的关系,重复第 2 步。直到当前墙的高度不大于栈顶高度或者栈空,然后把当前墙入栈,指针后移。
代码
class Solution {
public int trap(int[] arr) {
Stack<Integer> s=new Stack<>();
int i=0;
int res=0;
while(i<arr.length)
{
while(!s.isEmpty()&&arr[i]>arr[s.peek()])
{
int cur=s.pop();
if(s.isEmpty()) break;
int p=s.peek();
res+=(i-p-1)*(Math.min(arr[i],arr[p])-arr[cur]);
}
s.add(i++);
}
return res;
}
}
时间复杂度:虽然 while 循环里套了一个 while 循环,但是考虑到每个元素最多访问两次,入栈一次和出栈一次,所以时间复杂度是 O(n)。
空间复杂度:O(n)栈的空间。