木桶效应之攒青豆 | 青训营 X 码上掘金

101 阅读2分钟

当青训营遇上码上掘金

本次活动我选择的是主题四---攒青豆

一、题目分析

相信大家一看到这个问题就自然想到了木桶效应,想到木桶效应问题就已经解决一半了~

木桶效应:一只木桶能盛多少水,并不取决于最长的那块木板,而是取决于最短的那块木板。也可称为短板效应。

本次题目我们可以这样来理解,把这些柱子两个柱子为一组形成一个桶,题目就转化成了这些柱子能有多少个桶,构成桶的两个柱子是什么。

二、解决思路

很自然我们从左至右来找桶,而且我们只需要想出找第一个桶的方法,剩下的桶类比即可。

显然第一个柱子就是我们桶的左边界,所以我们只需要往右去找桶的右边界即可。

怎么去找右边界呢?

答:往右遍历木桶即可,若柱子比起始柱子高,我们就找到了,因为由于木桶效应再往后找就没有意义了,因为左边的柱子限制了青豆的数量;但是还存在一种可能,万一剩下的柱子没有比第一个柱子高的那怎么办呢?我们就选择剩下中最大的即可(就好像我们是从右往左找一样)。


看到评论说是接雨水,于是去leetcode搜了一下,并提交了一下,虽然效率很感人,但庆幸的是通过了...

8.png

三、代码

func zanqingdou(height []int) int {
	n := len(height)
	var nums int     //青豆数量统计
	var flag int     // 记录下一根柱子的位置
	var max int = -1 //记录剩下柱子中最大值
	var i, j int
	for i = 0; i < n; {
		for j = i + 1; j < n; j++ {
			//若发现存在柱子比边界柱子大自然退出,因为上限总是两边界柱子的最小值
			if height[j] > height[i] {
				flag = j
				break
			}
			//记录剩下中最大位置
			if height[j] > max {
				max = height[j]
				flag = j
			}
		}
		//取边界中的最小者
		var min int
		if height[i] <= height[flag] {
			min = height[i]
		} else {
			min = height[flag]
		}
		//统计这两根柱子之间的青豆,边界不计算
		for w := i + 1; w < flag; w++ {
			nums += min - height[w]
		}
		//更新柱子位置
		i = flag
		//初始化max
		max = -1
		//右边没有柱子,自然退出
		if i == n-1 {
			break
		}
	}
	return nums
}