最近发现一款在线代码编辑器,名字叫码上掘金,说到轻量代码编辑,我肯定第一时间想到vscode的网页版本,但今天这个和vscode还真就不一样,各有优劣,我真的很喜欢这款在线代码编辑器,它的用户界面美观,操作流畅,是一款非常好用的工具!
这是他一进去的场景,轻量、深色的背景十分讨喜,个人感觉,这款代码编辑器其实和vscode还是不太一样的,vscode主要是对一个项目进行编写,而码上掘金主要是保存代码片段,我个人理解,你可以拿来保存一些算法模板,例如二分查找模板、并查集模板、线段树模板等,很多算法都是有模板的,理解了之后就不需要重复的敲那些类似的代码了,直接把模板cv上去然后根据题意修改即可了
好的,言归正传,回到我们今天的算法题目:攒青豆
-
主题 4:攒青豆
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
以下为上图例子的解析:
输入:height = [5,0,2,1,4,0,1,0,3]
输出:17
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。
作者:青训营官方账号
链接:juejin.cn/post/717498…
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
思路:
看到这题,其实算是很经典单调栈应用题了,我们从前往后遍历与从后往前遍历,我们维护两个数组left与right,其中保存left数组负责保存左边比当前大的下一个元素,而right保存右边下一个更大元素
那么得到left和right之后我们遍历每个元素,对它的left[i]和right[i]进行处理就好
具体处理流程,首先接的求出能接到青豆的宽度,再求高度,ans += 高度 * 宽就可以了,当然这其中有个去重的问题,我们用set,用left[i], right[i], height[i]当key来去重
代码
也可以通过码上掘金查看到我的代码奥 攒青豆-单调栈
public class Solution {
public static void main(String []args) {
Solution main = new Solution();
int[] height = new int[]{4,2,0,3,2,5};
System.out.println(main.saveBeans(height));
}
public int saveBeans(int[] height) {
int ans = 0, n = height.length;
Deque<Integer> st = new ArrayDeque<>();
int[] right = new int[n];
int[] left = new int[n];
for (int i = n - 1; i >= 0; i--) {
while (!st.isEmpty() && height[i] >= height[st.peek()]) {
st.pop();
}
right[i] = st.isEmpty() ? i : st.peek();
st.push(i);
}
st.clear();
for (int i = 0; i < n; i++) {
while (!st.isEmpty() && height[i] >= height[st.peek()]) {
st.pop();
}
left[i] = st.isEmpty() ? i : st.peek();
st.push(i);
}
Set<List<Integer>> set = new HashSet<>();
for (int i = 0; i < n; i++) {
int currHeight = Math.min(height[left[i]], height[right[i]]) - height[i];
int currWidth = right[i] - left[i] - 1;
if (set.contains(Arrays.asList(left[i], right[i], height[i]))) continue;
set.add(Arrays.asList(left[i], right[i], height[i]));
ans += currHeight * currWidth;
}
return ans;
}
}
单调栈模板
没学过单调栈的同学可以看下这个oi-wiki单调栈 模板这东西,还是需要自己去总结,比如这题,我总结出了这个模板,将来类似的题就可以直接改改拿去用,需要改的地方我在注释上表明了
Deque<Integer> st = new ArrayDeque<>();
int[] right = new int[n];
int[] left = new int[n];
for (int i = n - 1; i >= 0; i--) {
// 判断条件
while (!st.isEmpty() && height[i] >= height[st.peek()]) {
st.pop();
}
// 栈空处理方法
right[i] = st.isEmpty() ? i : st.peek();
st.push(i);
}
st.clear();
for (int i = 0; i < n; i++) {
// 判断条件
while (!st.isEmpty() && height[i] >= height[st.peek()]) {
st.pop();
}
// 栈空处理方法
left[i] = st.isEmpty() ? i : st.peek();
st.push(i);
}