思维题(两点逼近)LeetCode11 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.

给定n条线段,每条线段的端点为(i,0)和(i,a[i]),现在需要在这n条线段中选择两条并与x轴组成一个水桶,求最大容量的水桶的容量(面积)。

 

暴力的方法就是直接枚举两条线段,找最大面积,这样复杂度是O(n^2)的。(没想到leetOJ居然还有稍强的数据,感觉是故意卡死这个复杂度的方法的。。)

 

我换了一个思路后,想到由于最后的最大面积一定是以某一个线段为桶的一侧(可能是左侧或者右侧)并且刚好淹没这条线段,那我们只需要枚举每条线段,然后找出这条线段左侧(或者右侧)比它高的最左(最右)的一个线段的位置,然后计算面积,并记录最大面积即可。

找到左侧比当前线段要高的最左侧线段的方法,可以直接将每个线段先按高度从大到小,再按坐标从小到大排序,然后扫描数组,记录 到当前的最小坐标,由于后扫描到的线段高度一定比先扫描到的高度小,所以只需要记录前面的坐标的最小值,便是当前线段的最左侧线段的坐标。时间复杂度O(nlogn)空间O(n)。

 

官网给出的标准方法,由于智力有限并不能想到,但是对其正确性还是可以给出证明。方法如下:

令指针i,j指向数组的开头和结尾,然后每次选取height[i]和height[j]较小的那个指针,并将指针想中间位置移动以为,并重新计算面积。(时间复杂度O(n),空间复杂度O(1))。

虽然我不能对这个方法有比较好的启发式的思维来想到,但是我至少还是得对其正确性给出证明,我的方法如下:

令a(i,j)表示线段i和j组成的面积(即a(i,j)=(j - i) * min{height(i), height(j)}),令DP(i,j)表示区间[i,j]的最大答案,则有:

DP(i,j) = max{DP(i+1,j), DP(i, j-1), a(i, j)}

只要证明当height(i) <= height(j)时,DP(i,j) = max{DP(i+1,j),a(i,j)}恒成立即可。

证明过程只需要分情况讨论即可:

1、若a(i,j) == DP(i,j) 这时结论显然成立。

2、若a(i,j) < DP(i,j) 

        1) 若DP(i+1, j-1) == DP(i,j)  这时,由于DP(i+1,j) >= DP(i+1, j-1),这时结论成立。

        2) 若DP(i+1, j-1) < DP(i,j)  这时有DP(i,j) = max{DP(i+1,j), DP(i, j-1)}

            因为DP(i + 1,j) = max{DP(i+1,j-1), a(i+1,j), a(i+2, j), ... , a(j - 1, j), a(j, j)}

            同时DP(i, j - 1) = max{DP(i+1,j-1), a(i, i), a(i,i+1), a(i, i+2), ... , a(i, j - 1)}

            因为height(i) <= height(j) 所以有max{a(i, i), a(i,i+1), a(i, i+2), ... , a(i, j - 1)} <= a(i, j) < DP(i, j)恒成立。

            所以 DP(i, j) = DP(i+1, j)。得证。

 

 1 public class Solution {
 2     public int maxArea(int[] height) {
 3         int maxarea = 0, l = 0, r = height.length - 1;
 4         while (l < r) {
 5             maxarea = Math.max(maxarea, Math.min(height[l], height[r]) * (r - l));
 6             if (height[l] < height[r])
 7                 l++;
 8             else
 9                 r--;
10         }
11         return maxarea;
12     }
13 }

 

posted @ 2016-09-06 14:08  再见~雨泉  阅读(380)  评论(3编辑  收藏  举报