今天给你们带来的是一道特别特别特别经典的题目接雨水问题,这个问题是不少算法书上面举例过的题目。虽然是难度题,可是相对来讲仍是比较容易理解的,代码长度也适中,说了这么多,就一个意思,你们记得打卡这个题目啊,真的是很nice的一道题,下面咱们来看一下题目描述。算法
给定 n 个非负整数表示每一个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨以后能接多少雨水。数组
示例 1:markdown
输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
复制代码
示例 2:ui
输入:height = [4,2,0,3,2,5]
输出:9
复制代码
示例3:spa
输入:[4,3,2,0,1,1,5]
输出:13
复制代码
上面是由数组 [4,3,2,0,1,1,5]表示的高度图,在这种状况下,能够接 13个单位的雨水(见下图)。3d
看了上面的示例刚开始刷题的同窗可能有些懵逼,那咱们结合图片来理解一下,咱们就用示例3的例子进行举例,他的雨水到底表明的是什么。code
上图则为咱们的题目描述,是否是理解了呢?你也能够这样理解咱们在地上放置了若干高度的黄色箱子,他们中间有空隙,而后咱们想在他们里面插入若干蓝色箱子,并保证插入以后,这些箱子的左视图和右视图都不能看到蓝色箱子。orm
好啦题目咱们已经理解了,下面咱们看一下解题思路。作这个这前咱们能够先去看一下咱们以前作过的另外一道题目每日温度。这两道题目的思路差很少,都是利用了单调栈的思想,下面咱们来看一下具体思路吧。索引
这里咱们也系统的说一下单调栈,单调栈含义就是栈内的元素是单调的,咱们这两个题目用到的都是递减栈(相同也能够),咱们依次将元素压入栈,若是当前元素小于等于栈顶元素则入栈,若是大于栈顶元素则先将栈顶不断出栈,直到当前元素小于或等于栈顶元素为止,而后再将当前元素入栈。就好比下图的4,想入栈的话则须要2,3出栈以后才能入栈,由于4大于他俩。图片
咱们了解单调栈的含义下面咱们来看一下接雨水问题到底该怎么作,其实原理也很简单,咱们经过咱们的例3来进行说明。
首先咱们依次入栈4,3,2,0咱们的数组前四个元素是符合单调栈规则的。可是咱们的第五个1,是大于0的。那咱们就须要0出栈1入栈。可是咱们这样作是为了什么呢?有什么意义呢?别急咱们来看下图。
上图咱们的,4,3,2,0已经入栈了,咱们的另外一个元素为1,栈顶元素为0,栈顶下的元素为2。那么咱们在这一层接到的雨水数量怎么算呢?2,0,1这三个元素能够接住的水为一个单位(见下图)这是咱们第一层接到水的数量。
注:能接到水的状况,确定是中间低两边高,这样才能够。
由于咱们须要维护一个单调栈,因此咱们则须要将0出栈1入栈,那么此时栈内元素为4,3,2,1。下一位元素为1,咱们入栈,此时栈内元素为4,3,2,1,1。下一元素为5,栈顶元素为1,栈顶的下一元素仍为1,则须要再下一个元素,为2,那咱们求当前层接到的水的数量。
咱们是经过2,1,1,5这四个元素求得第二层的接水数为1*3=3;1是由于min(2-1,5-1)=min(1,4)得来的,你们能够思考一下木桶效应。装水的多少,确定是按最短的那个木板来的,因此高度为1,3的话是由于5的索引为6,2的索引为2,他们之间共有三个元素(3,4,5)也就是3个单位。因此为6-2-1=3。
将1出栈以后,咱们栈顶元素就变成了2,下一元素变成了3,那么3,2,5这三个元素一样也能够接到水。
这是第三层的接水状况,可以接到4个单位的水,下面咱们继续出栈2,那么咱们的4,3,5仍然能够接到水啊。
这是咱们第四层接水的状况,一共可以接到5个单位的水,那么咱们总的接水数加起来,那就是
1+3+4+5=13。你学会了吗?别急还有动图咱们,咱们再来深刻理解一哈。
class Solution {
public int trap(int[] height) {
Stack<Integer> stack = new Stack<Integer>();
int water = 0;
//特殊状况
if(height.length <3){
return 0;
}
for(int i = 0; i < height.length; i++){
while(!stack.isEmpty() && height[i] > height[stack.peek()]){
//栈顶元素
int popnum = stack.pop();
//相同元素的状况例1,1
while(!stack.isEmpty()&&height[popnum] == height[stack.peek()]){
stack.pop();
}
//计算该层的水的单位
if(!stack.isEmpty()){
int temp = height[stack.peek()];//栈顶元素值
//高
int hig = Math.min(temp-height[popnum],height[i]-height[popnum]);
//宽
int wid = i-stack.peek()-1;
water +=hig * wid;
}
}
//这里入栈的是索引
stack.push(i);
}
return water;
}
}
复制代码
你们若是能感受到这个文章写的很用心的话,能给您带来一丢丢帮助的话,能麻烦您给这个文章点个赞吗?这样我就巨有动力写下去啦 你们须要更多经典题目的动图详解能够关注公众号:【袁厨的算法小屋】,更多精选算法题等着你呀,原创不易,感谢观看
