转载请标明来源(http://blog.csdn.net/lis_12/article/details/53178870)
#!/usr/bin/python
# -*- coding: utf-8 -*-
'''
英文:
Given n non-negative integers a1, a2, ..., an,
where each represents a point at coordinate (i, ai).
n vertical lines are drawn such that the two endpoints of line i is
at (i, ai) and (i, 0). Find two lines,
which together with x-axis forms a container,
such that the container contains the most water.
中文:给n个非负数a1, a2, ..., an,让(ix,ax),(iy,ay)与x轴组成容器,求容器最大容量
'''
class Solution(object):
def maxArea1(self, height):#常见方法,时间复杂度O(n*n)
"""
:type height: List[int]
:rtype: int
"""
length = len(height)
if length < 2:
return 0
max_area = 0
for i in range(length):
for j in range(i+1,length):
area = (j - i) * min(height[i],height[j])
if area > max_area:
max_area = area
return max_area
def maxArea(self,height):#时间复杂度O(n)
length = len(height)
if length < 2:
return 0
max_area = start = 0
end = length - 1
while start < end:
max_area = max(max_area,(end - start) * min(height[end],height[start]))
if height[start] <= height[end]:#横向不断变小的同时,只有竖向不断变大才可能超过之前的值
start += 1
else:
end -= 1
return max_area
if __name__ == "__main__":
s = Solution()
print s.maxArea([1,2,1])
时间复杂度O(n)代码说明
木桶容量取决于两边中较短的边,而且如果将较短的边换为更短边的话,容量只会变少;
因为S = (x1 - xn) * min(y1,yn),当(x1 - xn)越来越小,min(y1,yn)越来越大,S才可能变大;
方法
用两个指针从两端开始向中间靠拢,如果左端线段短于右端,那么左端右移,反之右端左移,知道左右两端移到中间重合,记录这个过程中每一次组成木桶的容积,返回其中最大的就为最大盛水量。解释如下。
解释
当height[L] < height[R]时,L与R左侧线段组成的木桶为什么没必要判断呢?
当左端线段height[L]小于右端线段height[R]时,我们将L右移,这时舍弃的是L与R左侧线段(R+1, R+2, …{R左侧的线段})组成的木桶,这些木桶是没必要判断的,因为这些木桶的容积肯定都没有L和R组成的木桶容积大。
为什么R+1, R+2, …与L组成的木桶肯定没有L和R组成的木桶容积大呢?
因为当左端线段L小于右端线段R,L较短,不管R+1, R+2…是否大于R,竖向最大值就为L,而且横向R - L最大,所以R+1, R+2, …与L组成的木桶肯定都没有L和R组成的木桶容积大。
当height[L] < height[R]时,L与R右侧线段组成的木桶为什么也没必要判断呢?
当height[L] < height[R],height[L]那么减小肯定不会使水的容量增大,只有height[L]增加才有可能使水的容量增大。
但是会不会有这种可能:当前的L 和 某个
k (k ∈ R-1,R-2...{R右侧线段})
组成的木桶是最大容量呢?肯定是不可能啊= =….因为按照移动规则,既然右指针从k 移动到了R,说明L的左边一定存在一个边界 j,使height[j] > height[k],那么[j, k]的容量肯定大于[L, k],所以[L,k]不可能是最大容量,L与R右侧的线段组成的木桶没有必要判断。
(通俗版:右侧能移动到R说明L左侧肯定存在一个大于height[k]的线段j,[j,k]的容量肯定大于[L,k],所以L与R右侧的线段组成的木桶肯定不是最大容量。)
综上所述,上述方法求解最大容量的方法正确。
继续优化
上述方法是可以优化的,不过没太大意义。。。
具体查找步骤:
- R1 < L1,向R1左侧寻找比R1大的值,比R1还小的没有比较的意义 ,因为S1 = (x_R1 - x_L1) * R1,横向不断减小,竖向还减小的话,肯定没有S1大;
- R2 > L1,同理,向L1右侧寻找比L1大的值;
- 重复直至两侧重合。
参考网址: