【LeetCode】11.Container With Most Water(Python)
Problem
给定n个非负整数a 1,a 2,…,a n ,其中每个表示坐标(i,a i)处的点。绘制n条垂直线,使得线i的两个端点位于(i,a i)和(i,0)。找到两条线,它们与x轴一起形成一个容器,这样容器就含有最多的水。
注意: 您可能不会倾斜容器,n至少为2。
上面的垂直线由数组[1,8,6,2,5,4,8,3,7]表示。在这种情况下,容器可容纳的最大水面积(蓝色部分)为49。
例:
输入: [1,8,6,2,5,4,8,3,7]
输出: 49
Algorithmic thinking
解法一:暴力法,O(n^2),取到最大值
解法二:两指针方法
这种方法背后的直觉是线之间形成的区域总是受到较短线高度的限制。此外,线越远,获得的区域越多。
我们取两个指针,一个在开头,一个在数组的末尾,构成行的长度。此外,我们维持一个变数maxarea存储到目前为止获得的最大面积。在每一步,我们找出它们之间形成的区域,更新maxarea并且由一个步骤移动指针指向朝向另一端的短线。
这种方法如何运作?
最初我们认为构成外部最多线的区域。现在,为了最大化面积,我们需要考虑较大长度的线之间的区域。如果我们试图将指针向内移动更长的线,我们将不会获得任何面积增加,因为它受到较短线的限制。但是,尽管宽度减小了,但根据相同的论点,移动较短线的指针可能会变得有利。这样做是因为通过移动较短线的指针获得的相对较长的线可以克服由宽度减小引起的面积减小。
Python3 solution
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
class Solution:
def maxArea(self, height):
"""
:type height: List[int]
:rtype: int
"""
"""
方法一:暴力法,可运行。但是提交超时,不可通过。
"""
# max_ = 0
# for i in range(len(height)):
#
# for j in range(i+1, len(height)):
# max_ = max(max_, min(height[i], height[j]) * (j - i))
#
# return max_
"""
方法二:分别从列表左右两端遍历(while),面积=短边*距离,哪边短遍历时+1,因为短的已达最大值。
"""
max_area = 0
i = 0
j = len(height) - 1
while i < j:
width = j - i
length = min(height[i], height[j])
volume = width * length
if max_area < volume:
max_area = volume
if length == height[i]:
i += 1
else:
j -= 1
return max_area
if __name__ == '__main__':
integer_list = [1, 3, 3, 9, 12, 1, 2, 43, 2, 23, 2, 2, 23, 23, 23, 2]
result = Solution().maxArea(integer_list)
print(result)
Summary
我们必须最大化可以在垂直线之间形成的区域,使用较短的线条作为长度,并且线条之间的距离作为形成区域的矩形的宽度。
解法二复杂性分析:
时间复杂度: O(n)单程。
空间复杂度: O(1)使用恒定空间。