Home Leetcode

11. Container With Most Water

You are given an integer array height of length nn. There are nn vertical lines drawn such that the two endpoints of the ithi^{th} line are (i,0)(i, 0) and (i,h[i])(i, h[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.

Constraints:

Where would a good place be to start with this problem? The brute force solution would require us to check every combination of indices and finding the maximum volume that way. Instead, let’s start with just how water volume is calculated here. Let v(i,j)v(i, j) be the volume of water held by the container formed by the line at the iith index and the jjth index, where

v(i,j)=min(h[i],h[j])ij.v(i, j) = \min(h[i], h[j])\cdot|i - j|.

The equation gives us some clues on where to start: it is made of 2 parts, min(h[i],h[j])\min(h[i], h[j]) and ij|i - j|.

  1. ij|i - j| is the distance between ii and jj: so to maximise it, we should first look at the indices that are the furthest apart, (0,n)(0, n).
  2. min(h[i],h[j])\min(h[i], h[j]) tells us that the limiting factor for volume is whichever line is shorter. Therefore to improve on v(i,j)v(i, j), we should replace whichever is smaller with a line that is bigger.
  3. v(i,j)v(i, j) is symmetrical: v(i,j)=v(j,i)v(i, j) = v(j, i).

Combined, our strategy takes shape: first start at the ends of the array, and continuously replace whichever line is shorter with the next line closer to the center, and repeat until the ends meet. We don’t have to check past that since the volume equation is symmetrical.

def maxArea(self, height: List[int]) -> int:
	l, r = 0, len(height) - 1
	max_vol = 0
	
	while l < r:
		volume = min(height[l], height[r]) * (r - l)
		max_vol = max(max_vol, volume)
		if height[l] < height[r]:
			l += 1
		else:
			r -= 1
	
	return max_vol

Let’s say min(h[i],h[j])=h[i]\min(h[i], h[j]) = h[i]. When we move to h[i+1]h[i + 1], we are essentially discarding all the pairs (i,i+1),,(i,j1)(i, i + 1), \dotsc, (i, j - 1) as not the optimal solution. How can we be so sure?

Consider one of those indices k{i+1,,j1}k \in \{i + 1, \dotsc, j - 1\}. First, notice that ik<ij|i - k| < |i - j|, so for v(i,k)v(i, k) to be the optimal solution we must have min(h[i],h[j])<min(h[i],h[k])\min(h[i], h[j]) < \min(h[i], h[k]).

Either way, none of those indices can be the optimal solution, so we are safe to discard them.

Time Complexity

Notice that l and r start at the ends of the array, and move towards each other one at a time. Since the while loop terminates when l >= r, the while loop iterates nn times. Each iteration is constant time, and since lines 1 and 2 as well as the return statement are constant time as well, the runtime complexity is in O(n)\mathcal{O}(n).

Space Complexity

The only space used is to store l, r, max_vol, and volume, which are all constant integers—thus the space complexity is constant, in O(1)\mathcal{O}(1).