当青训营遇上码上掘金
题目介绍
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
以下为上图例子的解析:
输入:height = [5,0,2,1,4,0,1,0,3]
输出:17
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。
思路分析
思路一、暴力破解
具体思路:使用双重循环,先遍历第一根柱子到最后一根柱子,再对内层的每根柱子的最左边和最右边分别进行遍历选出最大的,每一层左边最大设为leftMax,右边最大设为rightMax。再设一个累加器res,每次外循环后累加leftMax与rightMax的较小值与当前柱子高度差。
部分代码如下:
int res=0;
for(int i = 1; i < height.size()-1; i++){
int leftMax = 0,rightMax = 0;
for(int j = 0; j <= i; j++){
leftMax=max(leftMax,height[j]);
}
for(int j = i; j < height.size(); j++){
rightMax=max(rightMax,height[j]);
}
res += min(leftMax,rightMax) - height[i];
}
优缺点分析:思路简单,便于理解。时间复杂度为O(n2),效率低。
思路二、单调栈
单调栈就是比普通的栈多一个性质,即维护栈内元素单调
具体思路: 当前柱子如果小于等于栈顶元素,说明形不成凹槽,则将当前柱子入栈; 反之若当前柱子大于栈顶元素,说明形成了凹槽,于是将栈中小于当前柱子的元素pop出来。
从左到右遍历数组,遍历到当前柱子,记栈顶元素为top,下一个元素为left,根据以上规则一定存在height[top]<=height[left]。若是当前柱子height[i]>height[top],则说明形成可以攒青豆的凹槽区域,该区域的宽度为i-left-1,高度为height[left]与height[i]的较小值同栈顶height[top]的差值。根据宽度高度即可计算每一次循环中卡出的凹槽区域,将凹槽的大小累加到结果ans中
优缺点分析:时间复杂度低O(n),但栈的思想比较难以想到
代码展示
Go语言实现的单调栈代码,上传至码上掘金供参考。如有疏漏和不足,欢迎大家纠正!