卖萌的弱渣

I am stupid, I am hungry.

Container With Most Water

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

Solution

  • Java:
(Container-with-Most-Water.java) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Solution {
    public int maxArea(int[] height) {
        int water = 0;
        int left = 0;
        int right = height.length-1;
        while(left<right){
            int h = Math.min(height[left], height[right]);
            water = Math.max(water, h*(right-left));
            while (height[left] <= h && left<right) left++;
            while (height[right] <= h && left<right) right--;

        }
        return water;
    }
}
  • 时间复杂度O(n),两个指针i, j分别从前后向中间移动,两个指针分别表示容器的左右边界。每次迭代用当前的容量更新最大容量,然后把高度小的边界对应的指针往中间移动一位。 本文地址

  • 正确性证明:由于水的容量是有较小的那个边界决定的,因此某次迭代中,假设height[i] < height[j],那么j 减小肯定不会使水的容量增大,只有i 增加才有可能使水的容量增大。但是会不会有这种可能:当前的i 和 某个k (k > j)是最大容量, 这也是不可能的,因为按照我们的移动规则,既然右指针从k 移动到了j,说明i 的左边一定存在一个边界 m,使m > k,那么[m, k]的容量肯定大于[i, k],所以[i,k]不可能是最大容量。

(Container-with-Most-Water.py) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution(object):
    '''
    题意:任取两个a[i]、a[j] 使得min(a[i], a[j]) * abs(i - j)最大化
    用两个指针从两侧向中间扫描,每次移动数值较小的指针,用反证法可以证明
    总是可以得到最优答案
    '''
    def maxArea(self, height):
        left, right = 0, len(height) - 1
        ans = 0
        while left != right:
            if height[left] < height[right]:
                area = height[left] * (right - left)
                left += 1
            else:
                area = height[right] * (right - left)
                right -= 1
            ans = max(ans, area)
        return ans