[LeetCode] Container With Most Water

    当然可以用O(n^2)的方法暴力求解,但是题目出来肯定不是让我们暴力求解的。首先想到的是设计一个算法让问题规模不断缩小,这里在求解过程中的变化应该是单向的——比如让底边不断缩短。

    我们可以用双指针法,让左右指针向中间移动遍历数组,在这期间每次移动指针底边都缩短1,这时候的问题是,按照什么规则遍历可以保证扫过最大的储水量??在这里,每次向内移动的指针只能是较短边的那一个。

    证明:

    设容量最大时的状态为s,底边长b,两指针p1、p2指向的边长为l1,l2,容积=min(l1,l2)* b。

    如果没有遍历到这种情况,那么一定是其中一个指针p1还没有到达s时p1的位置,另一个指针p2已经越过了s时p2的位置。也就是说,在p2位于s状态的位置,下次循环就要向中间移动的一刻,较短边长为l2,而s状态下参与计算的壁高小于等于l2,同时底边长B大于s状态下的底边长b,容积 = l2 * B,比s状态下更大,s就不是容积最大的状态。

    所以,每次迭代,要得到大于等于V0的新容积,向内移动的指针只能是较短边的那一个。

    这时候可以写代码了,从两端开始,每次把较短边的指针向内移动一格,维护最大面积maxArea,遍历一次即得出答案。时间复杂度O(n)。

class Solution {
    public int maxArea(int [] height) {
		int left = 0, right = height.length-1;
		int maxArea = 0;
		while(left < right) {
			int tmp = (right-left)*Math.min(height[left], height[right]);
			maxArea = Math.max(maxArea, tmp);
			if(height[left] < height[right]) {//不要写成(left<right)
				left++;
			}else {
				right--;
			}
		}
		return maxArea;
	}
}

猜你喜欢

转载自blog.csdn.net/daniel_2046/article/details/80684547