Skip to main content

11. Container With Most Water

mediumAsked at JPMorgan

Given heights of vertical lines, find the two that form the rectangle with the largest water volume. JPMorgan asks this on SDE onsites because the two-pointer move-the-shorter-side argument is the canonical place to grade your invariant-narration skill.

By Alex Chen, Founder, InterviewChamp.AI · Last verified

Source citations

Public interview reports confirming this problem appears in JPMorgan loops.

  • Glassdoor (2026-Q1)Recurring JPMorgan SDE onsite array problem across Q1 2026.
  • LeetCode (2026-Q1)Tagged JPMorgan on the LeetCode company tag page.
  • Reddit r/cscareerquestions (2025-12)JPMC onsite write-up: 'asked container with most water, expected the move-shorter-side argument'.

Problem

You are given an integer array height of length n. There are n vertical lines drawn such that the two endpoints of the i-th line are (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 a container can store. Notice that you may not slant the container.

Constraints

  • n == height.length
  • 2 <= n <= 10^5
  • 0 <= height[i] <= 10^4

Examples

Example 1

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

Explanation: Lines at indices 1 and 8 with heights 8 and 7 form the rectangle 7 * (8-1) = 49.

Example 2

Input
height = [1,1]
Output
1

Approaches

1. Brute force every pair

For every (i, j), area = min(height[i], height[j]) * (j - i). Take the max.

Time
O(n^2)
Space
O(1)
function maxAreaBrute(height) {
  let best = 0;
  for (let i = 0; i < height.length; i++) {
    for (let j = i + 1; j < height.length; j++) {
      const area = Math.min(height[i], height[j]) * (j - i);
      if (area > best) best = area;
    }
  }
  return best;
}

Tradeoff: Correct but TLEs at n=10^5. Useful only as a baseline to motivate the two-pointer optimisation.

2. Two pointers, move the shorter side (optimal)

Start pointers at both ends. Compute area; move whichever side is shorter inward. Repeat until they meet.

Time
O(n)
Space
O(1)
function maxArea(height) {
  let l = 0;
  let r = height.length - 1;
  let best = 0;
  while (l < r) {
    const h = Math.min(height[l], height[r]);
    const area = h * (r - l);
    if (area > best) best = area;
    if (height[l] < height[r]) l++;
    else r--;
  }
  return best;
}

Tradeoff: O(n) time, O(1) space — provably optimal. The move-shorter-side invariant is the key insight: moving the taller side cannot increase area because the width strictly decreases and the height is still bounded by the shorter side.

JPMorgan-specific tips

JPMorgan SDE interviewers ask 'prove this is correct' on this problem more often than on any other two-pointer question. The expected proof is one sentence: 'Moving the taller side inward strictly decreases the width while the height is still capped by the shorter side, so it can never produce a better answer. Therefore the only useful move is to advance the shorter side.' Have that sentence ready before you write code.

Common mistakes

  • Moving both pointers inward on every step — wrong, you only move one (the shorter).
  • Computing area as max(height[l], height[r]) instead of min — water level is bounded by the shorter side.
  • Moving the taller side when the heights are equal — does not change correctness here but mis-applies the principle on follow-ups.
  • Forgetting to update best AFTER computing area but BEFORE moving pointers.

Follow-up questions

An interviewer at JPMorgan may pivot to one of these next:

  • Trapping Rain Water (LC 42) — extension where multiple bars trap water at once.
  • Largest rectangle in histogram (LC 84) — different problem, same invariant-style reasoning.
  • What if a third pointer were allowed (three-line container)?
  • What if heights stream in one at a time?

Solve it now

Free. No sign-up. Python and JavaScript run instantly in your browser.

Output

Press Run or Cmd+Enter to execute

FAQ

Why does moving the shorter side guarantee we don't miss the optimum?

Consider any pair (i, j) with height[i] < height[j]. Any pair (i, k) with k < j has width strictly less than j - i, and its area is bounded by min(height[i], height[k]) * (k - i) <= height[i] * (j - i). So none of these pairs can beat (i, j), and we can safely advance i past it without losing the optimum.

What if both heights are equal — which pointer should I move?

Either; the result is the same. By symmetry, neither future pair starting from the side you don't move can beat the current area. Most candidates write 'if shorter then advance left else advance right' and that handles the tie correctly because the equal case falls into the else branch.

Free learning resources

Curated free links for this problem.

Practice these live with InterviewChamp.AI

Drill Container With Most Water and other JPMorgan interview questions under real-loop conditions with instant feedback on your reasoning, complexity claims, and code.

Practice these live with InterviewChamp.AI →