当青训营遇上码上掘金
选择第四个主题,即“攒青豆”
主题四————攒青豆
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,
排列后如下图所示,此时均匀从上空向下撒青豆,
计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
以下为上图例子的解析:
输入:height = [5,0,2,1,4,0,1,0,3]
输出:17
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。
根据题目可知,需要用单调栈来解决这个问题。
单调栈分单调递增栈和单调递减栈,之所以选择单调递减栈,是因为
- 根据题目的理解,当找到一根比前面高的柱子,就可以计算接到的青豆单位数
- 所以需要使用单调递减栈。
维护一个单调栈,单调栈存储的是下标,满足从栈底到栈顶的下标对应的数组height中的元素递减。
在入栈的时候需要对更低的柱子入栈
当出现高于栈顶的柱子,就可以对前面柱子进行结算,计算之后出栈。
代码具体如下:
#include<bits/stdc++.h>
using namespace std;
int main() {
int ans = 0;
int m[10] = {5,0,2,1,4,0,1,0,3};
vector<int> height(m,m+9);
stack<int> st;
for (int i = 0; i < height.size(); i++)
{
while (!st.empty() && height[st.top()] < height[i])
{
int cur = st.top();
st.pop();
if (st.empty()) break;
int l = st.top();
int r = i;
int h = min(height[r], height[l]) - height[cur];
ans += (r - l - 1) * h;
}
st.push(i);
}
cout<<ans<<endl;
return 0;
}
单调栈知识点补充:
何为单调栈
栈内元素非递增或者非递减。另一种说法是从栈底到栈顶递增或者递减。在很多情况下,可能会出现相同的数字元素,所以称之为非递增或者非递减栈比递增、递减栈更合适。
显而易见,从单调栈的这种结构很容易联想到,在算法中,合理运用单调栈,能够将O(n^2)的时间复杂度优化到O(n),这就是技巧。相对的,空间复杂度会增加,因为需要动态维护一个栈。这里需要明白一点,算法里面,都是时间和空间的取舍,所谓的时空间转换指的就是这个,所以要根据具体场景去选择。
- 单调递增栈:单调递增栈就是从栈底到栈顶数据是从大到小
- 单调递减栈:单调递减栈就是从栈底到栈顶数据是从小到大
参考引用: 单调栈