LeetCode 11. 盛最多水的容器 线性解法的一种理解

题目描述

Given n non-negative integers a1, a2, ..., an , where each represents a point at coordinate (i, ai)n vertical lines are drawn such that the two endpoints of the line i is at (i, ai) and (i, 0). Find two lines, which, together with the x-axis forms a container, such that the container contains the most water.

Notice that you may not slant the container.

Example 1:

Input: height = [1,8,6,2,5,4,8,3,7]
Output: 49
Explanation: The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. In this case, the max area of water (blue section) the container can contain is 49.

这个题一开始的思路是暴力遍历,复杂度O(n^2).

看了一下题解,发现了一种线性解法,但是题解的解释有点太云里雾里,不太明白。最后自己考虑了一下之后发现其实是这样的:

首先是所有的线段是密集排布的,也就是说每个线段之间的间隔都是1.这样,如果从最外侧开始计算,记左边线段为L, 右边线段为R,他们之间的距离为D.

那么面积就是min(L,R)*D.

于是我们可以推断出一个事实:

那么就是因为我们是从最外侧开始计算,那么移动高的的那一侧是没有意义的,因为无论移动后高度变为多少,他的水面高度还是取决于矮的那侧。而且因为距离变短了。于是如果移动高的我们只可能得到一个比当前更小的面积。

因为新的D一定是小于原来的D,而且新的最矮线段绝对不大于原来的最矮值。

用公式表示就是,因为min(L', R') <= min(L,R)  and D' < D. 所以min(L', R')*D' 一定小于min(L,R)*D。

所以我们只能移动最短的那根线段。每移动一次就计算一次面积,然后再移动像对短的线段。而这样知道左侧等于右侧。我们就可以得到最终答案了。

比较抽象的地方是怎么通过n的操作排除掉了n^2的可能性。我觉的可以辅助图片来理解,以题目例题为例,一开始的情况为:

蓝色表示L的index,黄色表示R的index,因为L必须小于R,所以红色的为不可能的情况。

之后白色就是我们需要判断的所有可能了,很明显是个n^2的问题。

此时L=0, R=8

但是基于我们上面的推论,我们只能右侧,因为左侧高度为1,无论怎么移动右侧,都不可能得到一个大于当前面积的新面积了。于是我们直接排除了L=0时的所有可能。

同样的步骤,因为现在R为矮的一侧,我们可以排除所有 R = 8的所有可能

以此类推,我们每次都是排除n可能,所以,我们可以用n次操作来排除n^2的可能。

而过程中的最大值,就是我们的答案

代码:

class Solution:
    def maxArea(self, height: List[int]) -> int:
        maxArea = 0
        i = 0
        j = len(height)-1
        
        while i < j:
            area = j-i
            if height[i] < height[j]:
                area *= height[i]
                i += 1
            else:
                area *= height[j]
                j -= 1
            maxArea = area if area > maxArea else maxArea
            
        return maxArea

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值