11. 盛最多水的容器
11. 盛最多水的容器(Container With Most Water)
给定 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
切题
算法思路:
暴力法
在这种情况下,我们将简单地考虑每对可能出现的线段组合并找出这些情况之下的最大面积。
时间复杂度:
,计算所有
种高度组合的面积。
空间复杂度:
,使用恒定的额外空间。
leetcode 会超时失败
双指针法
两线段之间形成的区域总是会受到其中较短那条长度的限制。此外,两线段距离越远,得到的面积就越大。
我们在由线段长度构成的数组中使用两个指针,一个放在开始(容器左边),一个置于末尾(容器右边)。
使用变量 maxareamaxarea 来持续存储到目前为止所获得的最大面积。每次移动指向较短线段的指针向较长线段那端移动一步(从两边向中间移动)。
为什要那样移动呢?
容器左边 长为A,容器右边 长为B,中间距离为
从两边向中间移动(容器左边更左,以及容器右边更右的情况,已经在之前计算处理过了)。当前面积为
,从两边向中间移动,中间距离
必然减少,如果存在面积更大的情况,那么只能提高min(A,B) ,只有将较短线段的指针向较长线段那端移动,才有可能存在新的A1,B1,中间距离为(b1-a1),使得
更大。
详细证明
时间复杂度:
一次扫描
空间复杂度:
,使用恒定的额外空间。
边界情况:
双指针法 需要在 right < left 时结束移动,此时左右两指针已经在中间相遇
Python3 实现
暴力法
class Solution:
def maxArea(self, height: List[int]) -> int:
maxarea = 0 # 最大面积
length = len(height)
for i in range(0,length): # 一层循环,确定容器左边
for j in range(i+1,length): # 二层循环,确定容器右边
tmparea = min(height[i],height[j])*(j-i) # 计算存水容量
maxarea = max(maxarea,tmparea)
return maxarea
双指针法
class Solution:
class Solution:
def maxArea(self, height: List[int]) -> int:
maxarea = 0 # 最大面积
left = 0 # 左指针
right = len(height) - 1 # 有指针
while right > left:
curarea = (right - left) * min(height[left], height[right]) # 计算当前面积
maxarea = max(maxarea,curarea) # 最大面积
# 下面处理 应该哪个指针向中间移动
if height[left] <= height[right]:
left += 1 # 更大的面积只能是left向中间移动时出现
else:
right -= 1 # 更大的面积只能是right向中间移动时出现
return maxarea
GitHub链接:
https://github.com/lichangke/LeetCode
知乎个人首页:
https://www.zhihu.com/people/lichangke/
CSDN首页:
https://me.csdn.net/leacock1991
欢迎大家来一起交流学习