题目描述
盛最多水的容器
给定 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (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
解决方法
方法一:移动指针
- 装水的面积取决于两条线中较短的那条的长度和两条线之间横坐标的差值。
- 用双指针left、right,分别指向数组height的首尾。只有较短边会对盛水量造成影响,因此移动较短边的指针,并比较当前盛水量和当前最大盛水量。直至左右指针相遇。
- area在宽度变小的情况下,只有可能高度变大,面积才有可能变大
- 如果
height[left]
长度小于height[right]
,无论如何移动right
,短板在left
,不可能找到比当前记录的 area 更大的值了,只能通过移动left
来找到新的可能的更大面积。这种方式可以遍历到容量最大的情况。
class Solution:
def maxArea(self, height):
"""
:type height: List[int]
:rtype: int
"""
if height == []:
return 0
left, right, area = 0, len(height)-1, 0
while left<right:
area = max(area, min(height[left], height[right]) * (right-left))
if height[left]<height[right]:#area的高取决于左指针
left+=1
else: #area的高取决于右指针
right-=1
return area
Time Complexity: O ( n ) O(n) O(n)
方法一改进
class Solution(object):
def maxArea(self, height):
"""
:type height: List[int]
:rtype: int
"""
l = 0
r = len(height)-1
s = 0
while l < r:
width = r-l
if height[l] < height[r]:
h = height[l]
l += 1
else:
h = height[r]
r -= 1
s = max(s, h*width)
return s