📖 7 min read
Last updated on

Container With Most Water — Coding Interview Walkthrough


Hero Image for Container With Most Water

You’re in a coding interview. The interviewer gives you an array of heights and asks you to find the container that holds the most water. You write the nested-loop brute force in two minutes. It works. The interviewer says: “This is O(n^2). Can you do better?” You know it involves two pointers, but when they ask “How do you know you’re not skipping the optimal pair?”, you can’t answer. The correct code without the correct justification still looks like memorization.

This walkthrough covers both: the O(n) two-pointer solution and the greedy proof that makes it defensible under interview questioning.


The Problem

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 at (i, 0) and (i, height[i]).

Find two lines that together with the x-axis form a container that holds the most water. Return the maximum amount of water the container can store. You may not slant the container.

(LeetCode #11)

Example 1

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

Output 49

Example 2

Input height = [1, 1]

Output 1

In Example 1, the best pair is indices 1 and 8 (heights 8 and 7). Width = 7, height = min(8, 7) = 7, area = 49. The water level is limited by the shorter wall.

Already comfortable with the solution? Practice it in a mock interview →


What Interviewers Are Actually Testing

SkillWhat Interviewers Observe
Two-pointer pattern recognitionDo you identify this as a shrinking-window problem?
Greedy argumentCan you explain why moving the shorter pointer is always safe?
Area formulaDo you correctly compute min(height[left], height[right]) * (right - left)?
Proof by eliminationCan you argue that moving the taller pointer can never improve the answer?
Edge case awarenessDo you handle two-element arrays and arrays with equal heights?

Step 1: Clarifying Questions

1. Can heights be zero? A line of height zero forms a container with zero water. Your formula handles it naturally.

2. Are there at least two lines? LeetCode guarantees n >= 2. Your two-pointer initialization is always valid.

3. Can multiple pairs produce the same maximum area? Yes, but the problem only asks for the maximum value, not which pair.

4. Are heights always non-negative integers? Yes. This rules out negative heights.


Step 2: A First (Non-Optimal) Idea

Try every possible pair of lines:

def max_area_brute(height: list[int]) -> int:
    max_water = 0
    n = len(height)
    for left in range(n):
        for right in range(left + 1, n):
            width = right - left
            water = min(height[left], height[right]) * width
            max_water = max(max_water, water)
    return max_water

O(n^2) time, O(1) space. For n = 100,000, that’s 10 billion pair evaluations. The interviewer will ask you to do better.


Step 3: The Key Insight

Start with pointers at both ends (widest container). The only move that could improve the area is advancing the shorter pointer inward. Moving the taller pointer makes the container narrower while keeping the same height bottleneck, so the area can only decrease. Moving the shorter pointer loses width but might gain enough height to compensate. This greedy argument proves no optimal pair is ever skipped.

The formal argument: when height[left] <= height[right], every pair (left, x) for x < right has less width and the same height bottleneck (height[left]), so area(left, x) < area(left, right). We can safely discard all of them.

Bar chart of heights [1,8,6,2,5,4,8,3,7] with bars at indices 1–8 highlighted in teal, water level at height 7, and label showing area = min(8,7) × 7 = 49. ---

Step 4: Optimal Strategy

  1. Initialize left = 0, right = len(height) - 1, max_water = 0.
  2. While left < right:
    • Compute area = min(height[left], height[right]) * (right - left).
    • Update max_water.
    • If height[left] <= height[right], move left right. Else move right left.
  3. Return max_water.

Python Implementation

def max_area(height: list[int]) -> int:
    left, right = 0, len(height) - 1
    max_water = 0

    while left < right:
        width = right - left
        current_area = min(height[left], height[right]) * width
        max_water = max(max_water, current_area)

        # Move the shorter pointer inward
        if height[left] <= height[right]:
            left += 1
        else:
            right -= 1

    return max_water

Trace for height = [1, 8, 6, 2, 5, 4, 8, 3, 7]:

Stepleftrighth[l]h[r]widthareamaxmove
10817888left++
2188774949right—
3178361849right—
4168854049left++
5266842449left++
636283649left++
7465821049left++
856481449left++

max_water = 49


Time & Space Complexity

AspectComplexityExplanation
TimeO(n)Each pointer moves inward at most n times total
SpaceO(1)Only three integer variables

Common Interview Mistakes

  1. Moving the taller pointer instead of the shorter one. The height is still constrained by the shorter wall and the width has decreased. The area can only get worse.

  2. Using + instead of min() in the area formula. Water fills up to the shorter wall. Using sum or average is physically wrong.

  3. Computing width as right - left + 1. The width is the distance between walls: right - left, not right - left + 1.

  4. Stopping the loop with left <= right. When left == right, the container has zero width. The loop should end when pointers meet.

  5. Not being able to justify the pointer movement. Writing correct code without explaining why is a red flag. Prepare: “Moving the taller pointer can’t help because the height is still capped by the shorter wall and the width decreases.”

  6. Jumping to two pointers without mentioning brute force first. Naming the brute force and explaining why it’s insufficient shows reasoning, not memorization.


What a Strong Candidate Sounds Like

“The brute force checks every pair in O(n^2). To do better, I’ll use two pointers starting at the widest container: left at index 0, right at the last index. At each step I compute the area and decide which pointer to move. If I move the taller pointer, the width shrinks and the height stays capped by the shorter wall, so the area can only decrease. But if I move the shorter pointer, I might find a taller wall that compensates. So I always advance the shorter pointer. This guarantees I never skip a pair that could be optimal.”


Example Interview Dialogue

Interviewer: How do you know you’re not missing the optimal pair?

Candidate: By elimination. When the left pointer is shorter, every pair (left, x) for x < right has less width and the same height bottleneck, so their area is strictly less than (left, right). I can safely discard them all by advancing left. Same argument applies symmetrically.

Interviewer: What if both heights are equal?

Candidate: It doesn’t matter which pointer we move. Both are equally the “shorter” wall. I use <= to move left, but moving right is equally valid.

Interviewer: Could there be a solution better than O(n)?

Candidate: No. Any algorithm has to examine every element at least once. That’s an omega(n) lower bound, and our solution matches it exactly.


Container With Most Water is the cleanest introduction to the two-pointer greedy pattern. These problems extend it:


Practice This in a Mock Interview

Reading this explanation gives you the formula, the pointer logic, and the greedy argument. But the question “How do you know you’re not missing the optimal pair?” is almost always asked, and candidates who can’t answer it fluently leave doubt in the interviewer’s mind, even if their code is correct.

The only way to make the greedy justification feel natural is to practice saying it out loud, under pressure, more than once.

Start a mock interview for Container With Most Water on Intervu.

Further reading:

Practice Like It's the Real Interview

Get instant feedback on your approach, communication, and code — powered by AI.

Start a Mock Interview →