leetcode11. 盛最多水的容器

leetcode11. 盛最多水的容器

给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

**说明:**你不能倾斜容器,且 n 的值至少为 2。

leetcode11. 盛最多水的容器_第1张图片

示例:

输入:[1,8,6,2,5,4,8,3,7]
输出:49

方法:双指针

思路:

本题我们先提出方法,然后证明一下这个方法的正确性。

我们使用双指针,left在最左边,right在最右边。计算此时left和right构成的最大容积;然后我们将left和right中较短的边,向内移动一步(left++或right–),继续计算left和right的容积…继续移动,直到两个指针相遇,保存的之前遍历过的最大容积即为答案。

下面证明为什么这个方法是正确的。

当初始的左右指针位置时,此时容器的宽度是最长的,不存在宽度上升的情况,宽度只会减少。

那么我们为什么移动短边而不是长边呢?

因为容器的高度取决于两边中较短的边,我们移动短边(假设为left),保存长边,这样移动之后如果left很高,甚至比right更高,那么容器高度为right,下一次移动right,保存更高的left…这样不会错过任何一次容积上升的机会。

如果移动长边,那么就算长边移动之后再高,比如从2→100,但是由于此时左边还是更短的1,这个100是无用的,这就不对了。

总结起来就是,宽度是不断下降的,我们需要不错过每一次高度上升的机会,因此移动短边。

代码:

class Solution:
    def maxArea(self, height: List[int]) -> int:
        n = len(height)
        left = 0
        right = n-1
        ans = 0
        while left < right:
            ans = max(ans,min(height[left],height[right])*(right-left))
            if height[left] <= height[right]:
                left += 1
            else:
                right -= 1
        return ans

结果:

leetcode11. 盛最多水的容器_第2张图片

你可能感兴趣的:(Leetcode做题记录)