11. 盛最多水的容器 - 力扣(Leetcode)
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明: 你不能倾斜容器。
示例 1:
输入: [1,8,6,2,5,4,8,3,7]
输出: 49
解释: 图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
示例 2:
输入: height = [1,1]
输出: 1
思路
可以使用双指针,接下来需要讨论的是指针怎么移动的问题。如下图所示(与题中给的不一样,直接看下图就可以),开始的时候准备两个指针,各指向左右两端,向中间移动。
接下来的请带着一个问题思考:是谁在制约着水的体积。我们努力的目标应该是突破这个制约。
指针移动的目标就是使得水的区域变得更大,如果移动前就能明确移动后一定会变小,那还移动它干啥。只有可能变大的情况下,我们才移动。
上图所示的两条边,是指针初始时指向的两条边,其中一个高、另一个矮。
需要明确的是,无论移动哪个底边都会变小,这是毋庸置疑的。此时制约水体积的是矮的边,那就突破这个制约,矮的边不要了,移动矮的边。如果移动高的边,并不会改变矮边制约水体积的情况。因此,当边一高一矮的情况下,只有移动矮的边才可能获得更大的水体积。
当两条边同样高时,怎么移动呢?
事实上,当两条边同样高的时候,两条边都是水体积的制约条件。既然都制约,那么久都不要了,一起移动。
然后在移动的过程中,统计每次能获得水体积的最大值。直至两条边相遇。
代码
func maxArea(height []int) int {
i, j := 0, len(height)-1
res := 0
for i < j {
// 移动前计算一下水的体积,取最大值
v := (j - i) * min(height[i], height[j])
res = max(res, v)
// 两条边一边高,同时制约水的体积,就都不要了
if height[i] == height[j] {
i++
j--
}else if height[i] < height[j]{
i++
}else{
j--
}
}
return res
}
func min(a, b int)int{
if a < b {
return a
}
return b
}
func max(a, b int)int{
if a > b {
return a
}
return b
}