11_盛最多水的容器

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

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

直接两趟for循环暴力求解的话会超出时间限制,不可取
代码如下:

class Solution(object):
    def maxArea(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        res = 0 
        for i in range(len(height) - 1):
            for j in range(len(height)):
                area = (j - i) * min(height[i],height[j])
                res = max(res,area)

        return res

本题较优的解法是使用双指针
分析:
双指针简单来说就是,指针每一次移动,都意味着排除掉一个柱子。
本题的核心就是这个面积是由较短的柱子来决定的,这个影响到了每次指针的移动方向
容纳水量是由两个指向的数字中较小值 * 指针之间的距离所决定

双指针代表了什么?
双指针代表的是可以作为容器边界的所有位置的范围。在一开始,双指针指向数组的左右边界,表示数组中所有的位置都可以作为容器的边界,因为我们还没有进行任何尝试。在这之后,我们每次将对应的数字较小的那个指针往另一个指针的方向移动一个位置,就表示我们认为这个指针不可能作为容器的边界了。

解法一:

class Solution:
    def maxArea(self, height: List[int]) -> int:
        
        l, r = 0, len(height) - 1
        res = 0 
        
        while l < r:
            s = min(height[l], height[r]) * (r-l)
            res = max(res,s)

            if height[l] < height[r]:   # 对左右边界进行判断,始终是移动较小的那个指针
                l += 1
            else:
                r -= 1
        
        return res 

解法二(for循环):

class Solution:
    def maxArea(self, height: List[int]) -> int:
        l, r, width, res = 0, len(height) - 1, len(height) - 1, 0

        for i in range(width,0 , -1):   # 倒序遍历,width就是宽度
            if height[l] < height[r]:
                res, l = max(res, height[l]*i), l+1

            else:
                res, r = max(res,height[r]*i), r-1
            
        return res

解法三(优雅,五行解决):

class Solution:
    def maxArea(self, height: List[int]) -> int:
        res, l, r = 0, 0, len(height) - 1

        while l < r:
            h = min(height[l],height[r])
            res, l, r = max(res, h * (r - l)), l + (height[l] == h), r - (height[r] == h)

        return res 

这里巧妙的使用了这个height[l] == h

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值