攒青豆 | 主题创作

88 阅读2分钟

当青训营遇上码上掘金,一起来看看攒青豆这个题目。

题目:攒青豆

现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)

image.png

解题思路

我的思路:

  • 从高到低依次排列柱子高度,最高的两个柱子构成一个长方形的青豆区域
  • 从第三高的柱子开始,依次与最近的比它高的柱子构成一块区域,直到覆盖所有柱子

参考思路:

参考题目:(42. 接雨水 - 力扣(LeetCode))

解法一:按行求

就是先求高度为1的水,再求高度为2的水,再求高度为3的水。 整个思路就是,求第i层的水,遍历每个位置,如果当前的高度小于i,并且两边有高度大于等于i的,说明这个地方一定有水,水就可以加1。如果求高度为i的水,首先用一个变量temp保存当前累积的水,初始化为0。从左到右遍历墙的高度,遇到高度大于等于i的时候,开始更新temp。更新原则是遇到高度小于i的就把temp加1,遇到高度大于等于i的,就把temp加到最终的答案ans里,并且temp置零,然后继续循环。

解法二:按列求

求每一列的水,我们只需要关注当前列,以及左边最高的墙,右边最高的墙就够了。 装水的多少,当然根据木桶效应,我们只需要看左边最高的墙和右边最高的墙中较矮的一个就够了。

还有其他方法就不一一列举了。

参考链接:# 详细通俗的思路分析,多解法 来源:力扣(LeetCode)

题解

对比了自己的思路和参考思路,我觉得解法一的方法比较简单,选择解法一的思路。

语言:c++

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib> 
using namespace std;

int a[101]; 

int main() {
	int n;
	scanf("%d",&n);
	int h = 0;
	for(int i = 1; i <= n; i++) {
		scanf("%d",&a[i]);
		h = h>a[i]?h:a[i];
	}
	int ans = 0;
	for(int i = 1; i <= h; i++) {
		bool k = 0;
		int temp = 0;
		for(int j = 1; j <= n; j++) {
			if(a[j] >= i) {
				if(!k) {
					k = 1;
				}
				else {
					ans += temp;
					temp = 0;
				}
			}
			if(k && a[j] < i) {
				temp++;
			}
		}
	}
	
	printf("%d\n",ans);
}

输出结果:

image.png