原题:
Given n non-negative integers a 1 , a 2 , … , a n a_1, a_2, \dots, a_n a1,a2,…,an , where each represents a point at coordinate ( i , a i ) (i, a_i) (i,ai). n vertical lines are drawn such that the two endpoints of line i is at ( i , a i ) (i, a_i) (i,ai) and ( i , 0 ) (i, 0) (i,0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.
Note: You may not slant the container and n is at least 2.
The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. In this case, the max area of water (blue section) the container can contain is 49.
给定 n 个非负整数 a 1 , a 2 , … , a n a_1, a_2, \dots, a_n a1,a2,…,an ,每个数代表坐标中的一个点 ( i , a i ) (i, a_i) (i,ai) 。画 n 条垂直线,使得垂直线 i 的两个端点分别为 ( i , a i ) (i, a_i) (i,ai) 和 ( i , 0 ) (i, 0) (i,0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
注意:你不能倾斜容器,n 至少是2。【这里返回值返回area面积即可】
Example 1:
Input: [1,8,6,2,5,4,8,3,7]
Output: 49
My Solution
class Solution:
def maxArea(self, height):
"""
:type height: List[int]
:rtype: int
"""
if len(height) < 2:
return False
area = 0
for i in range(len(height)):
height_temp = 0
for j in range(len(height)-1, i, -1):
area_width = j - i
if height[j] < height_temp:
continue
else:
area_height = min(height[i], height[j])
area = max(area, area_width * area_height)
height_temp = max(height_temp, height[j])
return area
暴力法!两层循环遍历所有可能,返回最大面积即可!做过太多类似的就不具体介绍 。
自己加上了一点优化,就是当第二层遍历时,从后向前遍历,对于height[j] < heigt[j+i]直接舍掉。
然而,测试可行,提交发现有些样例无法通过,会超时噢:
原因你懂得!两层循环遍历所有的可能,计算量很大噢。
Reference solution
有这样一种双指针的方法,分别指向列表的两端,逐步向中间逼近,最后返回最大值。而逼近的方法是较高的那头不动,较低的那头向高的那头移动(向大佬低头!)原因很容易理解哈。代码实现如下,解释见代码注释:
class Solution:
def maxArea(self, height):
"""
:type height: List[int]
:rtype: int
"""
#定义初始面积为0,并用索引模拟指针指向两头
max_area = left = 0
right = len(height) - 1
#循环执行条件
while left < right:
#最大面积
max_area = max(max_area, (right - left) * min(height[left], height[right]))
#向大佬低头哈哈哈
if height[left] <= height[right]:
left += 1
else:
right -= 1
return max_area
总结
应该注意的点:
- 当两层遍历不满足时间复杂度要求时,应该考虑一下从两边向中间的策略。