Container With Most Water

Given n non-negative integers a1a2, ..., an, where each represents a point at coordinate (iai). n vertical lines are drawn such that the two endpoints of line i is at (iai) and (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.

这道题给出了一个序列,要求找出两根线使其和x轴之间的存储的水最多。注意这里最终盛多少水,不需要考虑中间的最低值,只需要考虑两边的边界。

leetcode给出的提示是用two  pointer来做,two pointer做了几题,基本是O(n)复杂度,使用贪心策略。

具体采用何种贪心策略,我也做了好几次选择,最终的选择如下:

1.给出l = 0, r = n-1.

2.当al < ar, l++,向右移动一步,否则 r--,向左移动一步。

首先说明为何采用此种策略。思考如下,转自Yangbing Shi的博客:

由于ai和aj (i<j) 组成的container的面积:S(i,j) = min(ai, aj) * (j-i)


所以对于任何S(i'>=i, j'<=j) >= S(i,j),由于j'-i' <= j-i,必然要有min(ai',aj')>=min(ai,aj)才行。同样可以采用头尾双指针向中间移动:

当a(left) < a(right)时,对任何j<right来说

(1) min(a(left),aj) <= a(left) = min(a(left), a(right))

(2) j-left < right-left
 
所以S(left, right) > S(left, j<right)。排除了所有以left为左边界的组合,因此需要右移left。同理,当a(left) > a(right)时,需要左移right。而当a(left) = a(right)时,需要同时移动left和right。
 
但是以上策略在排除一侧选择时,并不能保证选择另一侧可以得到比当前最大面积更大的面积,所以我们需要保存maxArea,并不断迭代,而不是用最终的l,r结果直接算出最大面积,这也是贪心和DP的区别之一。DP的状态通常可以直接得到全局最优解。
 
所以上述解法需要通过证明来证明可以使 maxArea保存全局最优,即l,r在某一时刻同时指向使maxArea最大的l*和r*
 
采用反证法来证明,即假设最终的结果并非全局最优。即存在l,r在某一时刻同时指向使maxArea更大的l*和r*为全局最优。再来考虑我们的算法,因为最终l和r的中止情况为l==r,所以l和r遍历了所有的下标index。左指针和右指针至少有一个曾经过全局最优的取值,即l到达l*或者r到达r*时,另一个不曾到达过,不然maxArea最终会记录了这个最大面积。不失一般性,假设l曾停在l*。因为l停在l*时,r不曾停在过r*上,所以当l停在l*后,后续只有l不停向右,经过了r*。
1)此时l停在l*上一段时间。r>r*,我们移动r,但是始终无法到达r*,移动r说明ar<al,但是a[j]>=a[r*](j>r*),所以min(a[l*],a[j])>=min(a[l*],a[r*]),显然由a[l*],a[j]组成的面积更大,与l*和r*为全局最优相违背。
2)r>r*,l到达l*后,继续向右,说明,
 
附上leetcode上的证明,我觉得Since our algorithm stops only if the two pointers meet. So, we must have visited one of them but not the other这块有问题,不是。

Here is the proof. Proved by contradiction:

Suppose the returned result is not the optimal solution. Then there must exist an optimal solution, say a container with aol and aor (left and right respectively), such that it has a greater volume than the one we got. Since our algorithm stops only if the two pointers meet. So, we must have visited one of them but not the other. WLOG, let's say we visited aol but not aor. When a pointer stops at a_ol, it won't move until

  • The other pointer also points to aol. In this case, iteration ends. But the other pointer must have visited aor on its way from right end to aol. Contradiction to our assumption that we didn't visit aor.

  • The other pointer arrives at a value, say arr, that is greater than aol before it reaches aor. In this case, we does move aol. But notice that the volume of aol and arr is already greater than aol and aor (as it is wider and heigher), which means that aol and aor is not the optimal solution -- Contradiction!

posted on 2016-05-29 12:19  Sheryl Wang  阅读(227)  评论(0编辑  收藏  举报

导航