本人一直在努力地积累Leetcode上用Python实现的题,并且会尽力讲清每道题的原理,绝不像其他某些博客简略地带过。
如果觉得讲的清楚,欢迎关注。
不讲暴力法,讲我对指针向中间移的算法的理解。
首先,我们思考一下这样一个事实,我们取头尾2个木板(最后一个边Index为n),让它们组成一个容器,则可以算出此时的盛水量。我们假设高度较矮的那个木板的index为0,也就是说假设第一根比最后一根矮。这个盛水量有一个意义,那就是它是最大的——对于任何以0为边的板来说。也就是说我们在任意再从所有板中选2个,保证选一个0的情况下 (比如说我们选0和n-1 两条边),它的盛水量一定小于等于我们头尾的盛水量。同理,选0和n边之间任意2条边(保证选0的情况下),0和n的盛水量都要比我们这选的任意2条边的盛水量大。也就是说进行完这一步之后,你永远不用再去算把0边包括在内的容器了,因为你算了也没用,我们已经算了一个大于等于它的结果,也就是第一次算的结果。而这一切都基于0边是较短的事实,如果0边较大,我们不能有这样的事实,也就是说我们不能保证你之后不用再去算包括0边的容器。既然包括0边的容器都不用再算了(因为我们得到了一个大于等于它们的结果),于是我们彻底摒弃包括0边的容器。也就是说看1边和尾边。这次我们假设尾边小于1边。这说明在1边到尾边的所有木板中,最大盛水量一定小于我们这一次算出的盛水量。可能有人会疑惑,为什么不用再计算以0边和尾边的结果了呢?因为我们在上一次的计算中已经计算过那一次的结果了。其实我们并没有去计算,因为那个结果一定小于等于以0边和尾边为容器的结果。
class Solution:
def maxArea(self, height):
i = 0
j = len(height) - 1
maxval = 0
while i < j:
maxval = max(maxval, min(height[i], height[j])*(j-i))
if height[i] < height[j]:
i += 1
else:
j -= 1
return maxval
这个算法的难点在于使用了前后2个指针,这样当i 与 j相遇时结束程序,能够只遍历一遍数组。
因为最大盛水量有这样的特性,2 条边的容器的最大盛水量大于等于较短边与这之间任意一条边的最大盛水量。
而且这个算法利用了这个特性来避免把每一次的结果都算出来,因为它每算一次,其实囊括了很多种遍历的情况,那些情况都被跳过忽略了,因为他们一定小于这一次计算的盛水量