【每日一题】【LeetCode】【第七天】【Python】盛最多水的容器

解决之路= =

因为是周日,找个中等题挑战一下。

题目描述

在这里插入图片描述

测试案例(部分)

在这里插入图片描述
在这里插入图片描述

第一次

想一下,因为涉及到底乘高,所以不能排序。逆序也没必要。

简化一下题干,盛水最多,也就是算面积最大,其实就是挑两个下标不同的“板”,然后根据“木桶原理”,挑出最短的“板”,然后底边乘侧边算出面积。

然后想一下是否有可以减少次数的机会。挑两个“板”就能想到两次循环,时间复杂度O(n²)。然后,很容易想到,下标为01的两个“板”和下标10的两个“板”情况是一样的,所以每轮循环只需要检测后面的下标就行,不需要检测前面的。

虽然说这样时间复杂度没变(n-1 + n-2 + ... + 1=(n-1)n/2 => 还是O(n²)),但是循环次数还是少了一些的。暂时没有想到其他更好的解法了,先暴力解出来。

class Solution(object):
    def maxArea(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        area = []
        n = len(height)
        # 双循环找“板”
        for k, v in enumerate(height):
            for i in range(k+1, n):
            	# 木桶原理,取最小
                h = min(v, height[i])
                # 面积算出来就追加到列表
                area.append((i - k) * h)
        # 列表最大值返回
        return max(area)

测试正确,提交试试。果然,第一次不过原则。

在这里插入图片描述

第二次

报错原因是超时,是因为输入的案例数据太大了,自己的代码虽然刻意减少了次数,但是时间复杂度还是O(n²),所以面对大量数据,花费的时间还是没有降下来。

想一想还有什么方法,最好是通过一重循环就可以解决问题。感觉用双指针前后夹出最大面积,但感觉不管通过什么办法去减少花费时间,最后都要算出所有两两搭配出的面积。算每种两两搭配的组合,肯定需要O(n²)的时间复杂度。。。。

看看万能的评论区吧。评论区都在说双指针法,但没有看到之前有人整理的多语言的实现总结,翻了很多,java实现或者c还是多。

看到一个老哥总结成了一句话,“较矮的一边向中间收缩寻找更大的容积,直到相遇”

在这里插入图片描述

看到这话,感觉很有道理。自己再来试着先不看他的代码,顺着这句话的思路实现一下。

class Solution(object):
    def maxArea(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        n = len(height)
        left = 0
        right = n-1
        area = []
        while left < right:
            area.append((right - left) * min(height[left], height[right]))
            # 哪边小,哪边移动。等于号无所谓,左右随便一个移动。
            if height[left] < height[right]:
                left += 1
            elif height[left] >= height[right]:
                right -= 1
        return max(area)

提交成功。

在这里插入图片描述

确实,双指针法可以帮助在O(n)的情况下算出最大面积的匹配。

之前以为双指针法只能在有序序列的情况下进行,所以没太多考虑到双指针法。自己一开始想到双指针法,也因为感觉双指针法还是需要遍历所有两两搭配出的面积。

但是自己没有想到,虽然双指针法还是需要遍历所有两两搭配出的面积,但是只用了一个循环就可以实现遍历所有两两搭配。以后遇到无序序列,只要感觉可能能用就用双指针法试试。

附件

每日打卡以后再加上背单词打卡,每天积累一点点。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值