leetcode 11 题解:python3@ 官方题解_暴力法_双指针法

leetcode

leetcode解题得的源码,解题思路在代码的注释里。

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

题目原址:https://leetcode-cn.com/problems/container...
使用:vscode

Brute-force/暴力法

通过递归的思想来用暴力法遍历所有数据
代码:

#
# @lc app=leetcode.cn id=11 lang=python3
#
# [11] 盛最多水的容器
#

# @lc code=start
from typing import List

class Solution:
    def __init__(self):
        self.maxContent = 0

    def force(self, height: List[int]) -> int:
        # print(len(height))
        # get the last one & del it
        last = height.pop()
        for key,value in enumerate(height):
            # Short board effect, get the minimm value between the last one & current value
            tmp = min(last,value)*(len(height)-key)
            self.maxContent = max(tmp,self.maxContent)
            # print(self.maxContent)
        if len(height) == 1:
            return self.maxContent
        else:
            #Iterativly call self.force() with new params height
            return(self.force(height))

    def maxArea(self, height: List[int]) -> int:
        return {
            0 :lambda height :self.force(height),
        }[0](height)
# @lc code=end

if __name__ == "__main__":
    solve = Solution()
    print(solve.maxArea([1,8,6,2,5,4,8,3,7]))

提交效果:

  • 42 / 50 个通过测试用例
  • 状态:超出时间限制

复杂度分析:

  • time complexity :$O(n^{2})$ ,计算所有$\frac{n(n-1)}{2}$ 种高度组合的面积
  • space complexity :$O(1)$,使用恒定的self.maxContent空间

Double-pointer/双指针法

传统方法,两个指针,分别指向the first onethe last one,另外使用self.maxContent来存储最大的面积。

最初我们考虑由最外围两条线段构成的区域。现在,为了使面积最大化,我们需要考虑更长的两条线段之间的区域。如果我们试图将指向较长线段的指针向内侧移动,矩形区域的面积将受限于较短的线段而不会获得任何增加。但是,在同样的条件下,移动指向较短线段的指针尽管造成了矩形宽度的减小,但却可能会有助于面积的增大。因为移动较短线段的指针会得到一条相对较长的线段,这可以克服由宽度减小而引起的面积减小。

两个指针相互靠近时,矩形的底是变小的,所以只有高变大才有可能面积变大,所以让短的向长的那个靠近。

代码:

#
# @lc app=leetcode.cn id=11 lang=python3
#
# [11] 盛最多水的容器
#

# @lc code=start
from typing import List

class Solution:
    def __init__(self):
        self.maxContent = 0

    def burte_force(self, height: List[int]) -> int:
        # print(len(height))
        # get the last one & del it
        last = height.pop()
        for key,value in enumerate(height):
            # Short board effect, get the minimm value between the last one & current value
            tmp = min(last,value)*(len(height)-key)
            self.maxContent = max(tmp,self.maxContent)
            # print(self.maxContent)
        if len(height) == 1:
            return self.maxContent
        else:
            #Iterativly call self.burte_force() with new params height
            return(self.burte_force(height))

    def double_pointer(self, height: List[int]) -> int:
        i, j= 0, len(height) - 1
        while i < j:
            # the pointers approach eacher other, their distance becomes smaller, so the only when the short one approach the long one the area can be larger.
            if height[i] < height[j]:
                self.maxContent = max(self.maxContent, height[i] * (j - i))
                # the left pointer move right
                i += 1
            else:
                self.maxContent = max(self.maxContent, height[j] * (j - i))
                # the right pointer move left
                j -= 1
        return self.maxContent
    def maxArea(self, height: List[int]) -> int:
        return {
            0 :lambda height :self.burte_force(height),
            1 :lambda height :self.double_pointer(height),
        }[1](height)
# @lc code=end

if __name__ == "__main__":
    solve = Solution()
    print(solve.maxArea([1,8,6,2,5,4,8,3,7]))

提交效果
Accepted

  • 50/50 cases passed (148 ms)
  • Your runtime beats 66.95 % of python3 submissions
  • Your memory usage beats 50.48 % of python3 submissions (14.6 MB)

复杂度分析:

  • time complexity : $O(n)$ ,双指针遍历一次底边宽度$N$。
  • space complexity :$O(1)$ ,使用恒定的self.maxContent空间
本作品采用《CC 协议》,转载必须注明作者和本文链接
文章!!首发于我的博客Stray_Camel(^U^)ノ~YO
讨论数量: 2
Jason990420

嗯, 也许点数不是只有9点, 也许是10000个点, 还有不同的排列组合, 我想简单了.

我用随机数生成了一个一万笔的列表
结果你的只要5ms, 我的要22ms, 果真如此

4年前 评论
Jason990420

148 ms ?? passed ??
我上传了一个, 每次执行代码的执行用时都不一样, 偏差太大了.

class Solution(object):
    def maxArea(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        L = len(height) - 1
        m1 = 0
        for i in range(L+1):
            d1 = d2 = 0
            for j1 in range(0, i):
                if height[j1]>=height[i]:
                    d1 = i-j1
                    break
            for j2 in range(L, i, -1):
                if height[j2]>=height[i]:
                    d2 = j2-i
                    break
            m = height[i]*max([d1, d2])
            if m > m1:
                m1 = m
        return m1

比较了一下你的代码和我的代码, 我的快些, 4 ~ 32 ms, 但是提交结果都是超出时间限制, 不知时间限制是多少?
而且怎么可能是ms级的 ? CPU有这么慢 ? 应该是μs级的吧. 我是这么测试的, 结果是
0:00:00.000013 (我的)
0:00:00.000067(你的)

from datetime import datetime
solve = Solution()
start = datetime.now()
for i in range(10000):
    result = solve.maxArea([1,8,6,2,5,4,8,3,7])
stop = datetime.now()
print((stop-start)/10000)
print(result)
4年前 评论
娃哈哈店长 (楼主) 4年前
娃哈哈店长 (楼主) 4年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!