Container With Most Water

83 阅读1分钟

You are given an integer array height of length n. There are n vertical lines drawn such that the two endpoints of the ith line are (i, 0) and (i, height[i]).

Find two lines that together with the x-axis form a container, such that the container contains the most water.

Return the maximum amount of water a container can store.

Notice that you may not slant the container.

Example:

image.png

Input: height = [1,8,6,2,5,4,8,3,7]
Output: 49
Explanation: The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. 
In this case, the max area of water (blue section) the container can contain is 49.

Train of thought

  • area = the abscissa of two vertical lines is subtracted * the height of the two vertical lines is small
  • Use two nested for loops to exhaustively enumerate all possibilities and find the maximum value

Solution

public static int maxArea(int[] height) {
    int maximumWater = 0;
    for (int i = 0; i < height.length; i++) {
        if (i < height.length - 1) {
            for (int j = i + 1; j < height.length; j++) {
                int container = (j - i) * Math.min(height[i], height[j]);
                maximumWater = Math.max(container, maximumWater);
            }
        }
    }
    return maximumWater;
}

The complexity

Time complexity: O(n²)

Space complexity: O(1)


When the value of n is small, this solution is ok, but when n is large enough, the problem arises, and the program running time times out, so how to solve it?

image.png


Train of thought after optimization

  • Using two pointers to traverse, one pointer start from left, another pointer start from right.
  • Move pointer which height is smaller, move both two pointers when the height is same. (left pointer move to right, right pointer move to left, until the two pointers coincide)

Solution of after optimizaiton

public int maxArea(int[] height) {
      int maximumWater = 0;
        int l = 0;
        int r = height.length - 1;

        while (l < r) {
            int container = (r - l) * Math.min(height[l], height[r]);
            if (height[l] < height[r]) {
                l++;
            } else if (height[l] > height[r]) {
                r--;
            } else if (height[l] == height[r]) {
                l++;
                r--;
            }
            maximumWater = Math.max(container, maximumWater);
        }
        return maximumWater;
    }

The complexity

Time complexity: O(n)

Space complexity: O(1)


Summary & comparison

Assume input: height = [1, 8, 6, 2, 5, 4, 8, 3, 7]

  1. Using the former way to calculate times of needed:

(n-1) + (n-2) + (n-3) + (n-4) + ... + 2 + 1 = n(n-1)/2 = 36 times

  1. Using the latter way to calculate tiems of needed: 7 times

Obviously, the latter way is more efficient.