第一次认真写题解,有几个原因,这个题目比较像17年校赛那道没做出来的题,
二是因为O(n^2)的算法python实现超时了,java没超时,所以必须想一个更快的算法。
三是因为忘记把py项目里的venv加入到.gitignore,想把多个文件夹下的venv删除废了点功夫(不好好看文档的后果)
问题描述:给定一个容器,里面有多个间距为1,长度不同的挡板,给定一个整数数组, 代表挡板的高度。问如何装水试水最多?
方法一:O(n^2)的暴力写法,枚举两个端点,然后短的一边*间距 取最大值即可,java通过,py超时。
方法二:类似贪心算法。使用两个指针,指向数组首尾,同时向中间移动。问题在于,移动哪一边的指针?比较容易能猜出移动指向的值较小的那一边。
论证如下:
我们先假设 左端点的值小于有端点的值,我们无脑把左端点右移,比较移动后的右端点和左端点的值。
-
左<右
容器高度取决于左边,与原容器相比,低变短,高也变短,容积小于原容器
-
左==右
高度不变,底变短,容积小于元容器
-
左>右
高度取决于右边,与原容器相比,底变短,高不变,容积小于原容器
综上所述,移动较长一边的端点得到的结果总比原来差,不符合贪心的准则。所以我们移动较短的一边即可得到最优解。
class Solution:
def maxArea(self, height):
maxV = 0
i = 0
j = len(height) - 1
while i < j:
t = (j - i) * min(height[i], height[j])
maxV = max(maxV, t)
if height[i] < height[j]:
tt = height[i]
i += 1
while i < j and height[i] < tt:
i += 1
else:
tt = height[j]
j-=1
while i < j and height[j] < tt:
j -= 1
return maxV