当青训营遇上码上掘金
「青训营 X 码上掘金」—— 攒青豆
初见题目
- 现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
以下为上图例子的解析:
输入:height = [5,0,2,1,4,0,1,0,3]
输出:17
解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。
刚刚开始看见这个题目的时候,心中感慨万分,为什么策划们要出这个题目,或者说题目为什么要起这个名字,不过确实很应景,作为青训营的一员,在学习到知识的基础上,攒青豆似乎是最重要的事情,攒青豆的规则和活动有很多,如何才能不混乱,慢慢的攒够青豆呢!本人实力不济,算法题刷的不多,写出的算法或许不是最优解。不如先来一道攒青豆的算法题清醒下脑子吧!!!
题目思路
- 首先能够攒住青豆的前提是两侧需要有柱子包围,即左右两侧的高度都要大于0。正如“短板效应”一样,所能攒住的青豆要取决于矮的柱子。
- 那么我们就可以用(双指针法)两个int值来记录左边和右边的已知最高高度,随着指针的移动,int值会发生变化。
- 左指针l指向左边第一个柱子,右指针k指向右边第一个柱子,然后从左向右遍历
- 若遍历点的柱子高度小于l和k的值,那么当前遍历点所能存储的青豆个数为min{l,k}-当前柱子高度
- 若遍历点的柱子高度大于l,则l更新为当前柱子高度,左指针向右移动
- 比较左右指针的值,让值小的一方进行移动
代码如下所示
public int qingdou(int[] height)
{
if(height==null||height.length==0){
return 0;
}
int left = 0;
int right = height.length-1;
int sum = 0;
int l = height[left];
int k = height[right];
while(left<right){
if(l<=k){
if(l>height[left+1]){
sum+=l-height[left+1];
}else{
l = height[left+1];
}
left++;
}else{
if(k>height[right-1]){
sum+=k-height[right-1];
}else{
k = height[right-1];
}
right--;
}
}
return sum;
}