一、问题描述:
Given n non-negativeintegers a1, a2, ..., an, where each represents a point atcoordinate (i, ai). n verticallines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which togetherwith x-axis forms a container, such that the container contains the most water.
Note: You maynot slant the container and n is at least 2.
二、问题分析:
根据问题描述,大致分析需求为:在a1, a2, ..., an中找出两个元素,不妨设为ai和aj。通过这两个元素构获得四个点(i, ai)、(i, 0)、(j, aj)和(j, 0)。在坐标系上分别连接(i, 0)和(j, 0)、(i, 0)和(i, ai)、 (j, 0)和(j, aj) 构造出以一个开口向上的二维容器,大致图像如下:
容器的容量由两个因素决定:
1. i和j的距离;
2. ai和aj的最小值;
容量大小公式为:|i-j| * min{ai, aj}
那么,这样就可以把问题简化为:给定一个包含n个整数(a1, a2, ..., an)的列表。要求找出两个元素ai和aj,满足|i-j| * min{ai, aj} 为最大值。
三、算法设计:
1. 初始化最大容量max = 0,分别定义a = 0, b = len(l)
2. 当a < b 时,循环执行以下操作:
从给定的列表l两头开始往列表中部遍历,每次记录temp = min{l[a],l[b]} * (b – a),比较temp与max的大小。如果temp > max,则max = temp。
若l[a] > l[b],则b = b-1;
反之,则a = a + 1;
3. 返回的max即为最大容量
原理:
因为从列表的两头往中间遍历即能保证每次两个元素的下标之差是最大的,且不会重复计算。因为容量由两个元素数据的最小值决定,所以在每次记录完只需要将较小的一个元素进行替换,替换出现两种情况:①更新元素后容器的容量比未更新的小,但是这对记录的最大容量不产生影响;②更新元素后的容器容量比未更新的大,此时就会更新记录的最大容量。这样设计的优点是可以避免计算包含有较小元素的容量计算,这是因为针对一个特定的元素,由于较大或较小两个元素是往中间靠拢的距离,所以更新较大或较小的元素与另一个特定的元素组合的距离是一样的,因此包含较小元素的容器容量一定比包含有较大元素的容器容量小。
四、程序实现:
class Solution:
def maxArea(self, height):
"""
:type height: List[int]
:rtype: int
"""
n = len(height)
a = 0
b = n-1
max = 0
while(a < b):
temp = (b-a)*min(height[a], height[b])
if( temp > max):
max = temp
if (height[a] < height[b]):
a+=1
else:
b-=1
return max