The Container With Most Water is a classic problem in algorithmic and computational thinking, that is often used to test the efficiency and problem-solving skills of developers.

The problem statement is as follows:

You are given a list of n non-negative integers, where each integer represents a vertical line at position i with a height of height[i]. The width of each vertical line is 1. Find two lines, which, together with the x-axis, forms a container that contains the most water.

In other words, you need to find two vertical lines in the list that create the largest possible rectangle with the x-axis. The area of the rectangle represents the amount of water that the container can hold.

For example, consider the following input list of heights:Leetcode 463 Island Perimeter

heights = [1, 8, 6, 2, 5, 4, 8, 3, 7]

The figure below shows the list of heights as vertical lines, and the largest container that can be formed by selecting the lines at indices 1 and 8 (highlighted in red). The area of this container is 49 (7×7).

              |          
        |     |          
        |     |          
        |     |     |    
  |     |     |     |    
  |     |     |     |    
  |     |     |     |  | 
--|-----|-----|-----|--|
  1     8     6     2  5  4  8  3  7

In this case, selecting any other pair of lines would result in a smaller container.

Here are three approaches to solve the Container With Most Water problem, along with their pseudocode and explanations:

Approach 1: Brute Force

One simple approach to solving this problem is to use a brute force approach, which involves comparing every pair of lines and finding the one with the largest container.

max_area = 0
for i = 0 to n-1 do
  for j = i+1 to n-1 do
    area = (j - i) * min(height[i], height[j])
    max_area = max(max_area, area)
return max_area

We use a nested loop to iterate over every possible pair of lines. For each pair of lines, we calculate the area of the container that they form by multiplying the difference in their indices by the minimum height between them.

We then update a variable max_area with the maximum area we have found so far. Finally, we return max_area.

The time complexity of this approach is O(n^2), because we visit each pair of lines exactly once.

Approach 2: Two-Pointer Approach

A more efficient approach to solving this problem is to use the two-pointer approach.

max_area = 0
left = 0
right = n-1
while left < right do
  area = (right - left) * min(height[left], height[right])
  max_area = max(max_area, area)
  if height[left] < height[right] then
    left = left + 1
  else
    right = right - 1
return max_area

We start with two pointers, one at the beginning of the list (left) and one at the end (right). We then calculate the area of the container formed by these two lines, and update max_area with the maximum area we have found so far.

We then move the pointer with the smaller height inward (i.e., if height[left] < height[right], we move the left pointer to the right, otherwise we move the right pointer to the left). We repeat this process until the left and right pointers meet in the middle of the list.

The time complexity of this approach is O(n), since we visit each element in the list exactly once.

Approach 3: Using Stack

Another approach is to use a stack to keep track of the indices of the lines in the list. We can use the stack to keep track of the lines that might be useful in forming a larger container.

max_area = 0
stack = []
for i = 0 to n-1 do
  while stack is not empty and height[i] > height[stack.top()] do
    top = stack.pop()
    if stack is not empty then
      width = i - stack.top() - 1
    else
      width = i
    area = width * height[top]
    max_area = max(max_area, area)
  stack.push(i)
while stack is not empty do
  top = stack.pop()
  if stack is not empty then
    width = n - stack.top() - 1
  else
    width = n
  area = width * height[top]
  max_area = max(max_area, area)
return max_area

We start by initializing an empty stack. We then iterate through the list of heights. For each height, we check if the height is greater than the height at the top of the stack. If it is, we pop the top element from the stack and calculate the area of the container that

The two-pointer approach is generally considered to be the best approach for solving the Container With Most Water problem, because it has a time complexity of O(n), which is optimal for this problem.

The brute force approach has a time complexity of O(n^2), which is not efficient and will not work for large input sizes. The stack-based approach also has a time complexity of O(n), but it has higher constant factors and uses more memory than the two-pointer approach.

In addition, the two-pointer approach is simpler to understand and implement than the stack-based approach, and it does not require any additional data structures.

Therefore, the two-pointer approach is the recommended approach for solving the Container With Most Water problem.

Container With Most Water: Java Solution

public int maxArea(int[] height) {
    int maxArea = 0;
    int left = 0;
    int right = height.length - 1;
    
    while (left < right) {
        int area = Math.min(height[left], height[right]) * (right - left);
        maxArea = Math.max(maxArea, area);
        if (height[left] < height[right]) {
            left++;
        } else {
            right--;
        }
    }
    
    return maxArea;
}

Container With Most Water: JavaScript Solution

function maxArea(height) {
    let maxArea = 0;
    let left = 0;
    let right = height.length - 1;
    
    while (left < right) {
        const area = Math.min(height[left], height[right]) * (right - left);
        maxArea = Math.max(maxArea, area);
        if (height[left] < height[right]) {
            left++;
        } else {
            right--;
        }
    }
    
    return maxArea;
}

Container With Most Water: Python Solution

def maxArea(height):
    maxArea = 0
    left = 0
    right = len(height) - 1
    
    while left < right:
        area = min(height[left], height[right]) * (right - left)
        maxArea = max(maxArea, area)
        if height[left] < height[right]:
            left += 1
        else:
            right -= 1
    
    return maxArea

Container With Most Water: Ruby Solution

def max_area(height)
    max_area = 0
    left = 0
    right = height.length - 1
    
    while left < right
        area = [height[left], height[right]].min * (right - left)
        max_area = [max_area, area].max
        if height[left] < height[right]
            left += 1
        else
            right -= 1
        end
    end
    
    return max_area
end

The general idea behind the two-pointer approach is to use two pointers to explore the solution space in a more efficient way than brute force.

In the case of the Container With Most Water problem, we can use two pointers left and right to represent the two lines that form the container.

We start with left at the beginning of the list and right at the end of the list. We calculate the area of the container formed by these two lines using the formula:

area = (right - left) * min(height[left], height[right])

We then update a variable maxArea with the maximum area we have found so far, and then move the pointer with the smaller height inward. We repeat this process until the pointers meet in the middle of the list.

Written by

With 10+ years in software engineering, I specialize in blogging and web development. My skills span front-end, back-end, database design, web security, and SEO. Passionate about crafting helpful digital experiences.