DSA Series Day 9 Container With Most Water in Java, Python and Rust

Welcome to Day 9 of the Tekraze DSA series, where Container With Most Water shows that two pointers can win even on an unsorted array. Over the last few days we used two pointers on sorted arrays and strings. Today the array is not sorted at all, and the pattern still works.

Container With Most Water is a favourite interview question because the code is tiny, but the reason it works takes some real thinking.

Also Read: Two Sum II (Day 7) and 3Sum (Day 8) use the same two pointer idea on sorted arrays.

What is the Container With Most Water problem?

You get an array height where each value is a vertical wall standing at that index. Pick two walls. Together with the floor they form a container, and the water it holds is the shorter wall times the distance between them. Return the largest amount of water any pair of walls can hold. You can also try it on LeetCode once you finish reading.

text

Input:  height = [1, 8, 6, 2, 5, 4, 8, 3, 7]
Output: 49
Why:    walls at index 1 (height 8) and index 8 (height 7)
        min(8, 7) * (8 - 1) = 7 * 7 = 49

Input:  height = [1, 1]
Output: 1
Container With Most Water diagram where the shorter wall caps the water level
DSA Series Day 9: Container With Most Water in Java, Python and Rust 7

How should you think about Container With Most Water in plain words?

Water can never rise above the shorter wall, so the shorter wall is the one holding you back. Start with the widest container, one pointer at each end. Now ask which pointer is worth moving.

If you move the taller wall inward, the width shrinks and the height is still capped by the same short wall, so the area can only get worse. The only move that can possibly help is dropping the shorter wall and hoping to find a taller one.

That single observation gives you a one pass solution.

What does the brute force solution look like?

Check every pair of walls for Container With Most Water and keep the best area.

python

def max_area_brute(height):
    best = 0
    n = len(height)
    for i in range(n):
        for j in range(i + 1, n):
            best = max(best, min(height[i], height[j]) * (j - i))
    return best

Time is O(n²) because every pair is checked. Space is O(1). With 100,000 walls that is around five billion pairs, far too slow.

How do we get the optimal Container With Most Water solution?

Put left at index 0 and right at the last index. Work out the area, update the best answer, then move whichever pointer sits on the shorter wall. If both walls are equal you can move either one, because neither of them can be part of a bigger container with anything in between. Stop when the pointers meet.

Time is O(n) since each step moves one pointer closer and they meet after at most n steps. Space is O(1) because we only keep a few variables. If you want a refresher on why going from O(n²) to O(n) matters so much, our Big O helper post on time and space complexity walks through it with charts.

Container With Most Water walkthrough, one step at a time

Here is the pointer trace for [1, 8, 6, 2, 5, 4, 8, 3, 7]. Notice that the best area of 49 appears on the second step, and the loop keeps going only to prove nothing beats it.

Step Left Right Area Best So Far Move
1081 × 8 = 88Left (1 < 7)
2187 × 7 = 4949Right (8 > 7)
3173 × 6 = 1849Right
4168 × 5 = 4049Right (Equal walls)
5154 × 4 = 1649Right
6145 × 3 = 1549Right
7132 × 2 = 449Right
8126 × 1 = 649Right, then stop
Step 1 Move Left
Left0
Right8
Area1 × 8 = 8
Best So Far8
Reason1 < 7
Step 2 Move Right
Left1
Right8
Area7 × 7 = 49
Best So Far49
Reason8 > 7
Step 3 Move Right
Left1
Right7
Area3 × 6 = 18
Best So Far49
Step 4 Move Right
Left1
Right6
Area8 × 5 = 40
Best So Far49
ReasonEqual walls
Step 5 Move Right
Left1
Right5
Area4 × 4 = 16
Best So Far49
Step 6 Move Right
Left1
Right4
Area5 × 3 = 15
Best So Far49
Step 7 Move Right
Left1
Right3
Area2 × 2 = 4
Best So Far49
Step 8 Stop
Left1
Right2
Area6 × 1 = 6
Best So Far49
Next MoveMove right, then stop when pointers meet
 Container With Most Water two pointers moving inward from both ends of the bars
DSA Series Day 9: Container With Most Water in Java, Python and Rust 8

Container With Most Water in Java

java

// Two pointers from both ends, always move the shorter wall
public class Solution {
    public static int maxArea(int[] height) {
        int left = 0, right = height.length - 1, best = 0;
        while (left < right) {
            int h = Math.min(height[left], height[right]);
            best = Math.max(best, h * (right - left));
            if (height[left] < height[right]) {
                left++;
            } else {
                right--;
            }
        }
        return best;
    }

    public static void main(String[] args) {
        int[][] tests = {{1, 8, 6, 2, 5, 4, 8, 3, 7}, {1, 1}, {4, 3, 2, 1, 4}, {1, 2, 1}, {0, 0}, {5}};
        int[] expected = {49, 1, 16, 2, 0, 0};
        for (int i = 0; i < tests.length; i++) {
            int got = maxArea(tests[i]);
            System.out.println((got == expected[i] ? "PASS " : "FAIL ") + got);
        }
    }
}

Container With Most Water in Python

python

# Two pointers from both ends, always move the shorter wall
def max_area(height):
    left, right, best = 0, len(height) - 1, 0
    while left < right:
        h = min(height[left], height[right])
        best = max(best, h * (right - left))
        if height[left] < height[right]:
            left += 1
        else:
            right -= 1
    return best


if __name__ == "__main__":
    tests = [([1, 8, 6, 2, 5, 4, 8, 3, 7], 49), ([1, 1], 1), ([4, 3, 2, 1, 4], 16),
             ([1, 2, 1], 2), ([0, 0], 0), ([5], 0)]
    for h, want in tests:
        got = max_area(h)
        print("PASS" if got == want else "FAIL", got)

Container With Most Water in Rust

rust

// Two pointers from both ends, always move the shorter wall
fn max_area(height: &[i32]) -> i32 {
    if height.len() < 2 {
        return 0;
    }
    let (mut left, mut right, mut best) = (0usize, height.len() - 1, 0);
    while left < right {
        let h = height[left].min(height[right]);
        best = best.max(h * (right - left) as i32);
        if height[left] < height[right] {
            left += 1;
        } else {
            right -= 1;
        }
    }
    best
}

fn main() {
    let tests: Vec<(Vec<i32>, i32)> = vec![
        (vec![1, 8, 6, 2, 5, 4, 8, 3, 7], 49),
        (vec![1, 1], 1),
        (vec![4, 3, 2, 1, 4], 16),
        (vec![1, 2, 1], 2),
        (vec![0, 0], 0),
        (vec![5], 0),
    ];
    for (h, want) in tests {
        let got = max_area(&h);
        println!("{} {}", if got == want { "PASS" } else { "FAIL" }, got);
    }
}

The tests cover the classic [1, 8, 6, 2, 5, 4, 8, 3, 7] case, two equal walls, equal walls at both ends, a small peak in the middle, all zero heights and a single wall. Every test passed in Java, Python and Rust. The Rust version returns early for fewer than two walls so len() - 1 never underflows. For the helper functions used above, see the official docs for Math.min in Java, min in Python and i32 in Rust.

What are the tips and tricks for an easy Container With Most Water solution?

  1. Spot the pattern. When you pick two positions, as in Container With Most Water, and the score depends on their distance and the smaller of two values, think two pointers starting at both ends.
  2. Remember one rule. Always move the shorter wall. Say it out loud in the interview, then explain why moving the taller one can never help.
  3. Do not sort. The positions matter here, so sorting would destroy the distances.
  4. Watch the edge cases. An array with one wall holds nothing, zero heights hold nothing, and equal walls are fine to move either way.
  5. Know the cousin. Trapping Rain Water looks similar but counts water above every bar, so it needs left and right max heights. Mention the difference if asked.

What are the common mistakes people make?

These are the slips we see most often on Container With Most Water.

  • Using the taller wall as the height instead of the shorter one.
  • Moving the taller pointer, which can skip past the real answer.
  • Forgetting that width is right - left, not the number of walls between them.
  • Mixing this up with Trapping Rain Water and summing water above every bar.
  • Sorting the array first, which breaks the positions.
Container With Most Water versus Trapping Rain Water shown side by side
DSA Series Day 9: Container With Most Water in Java, Python and Rust 9

Where does the Container With Most Water pattern show up beyond interviews?

You will rarely meet Container With Most Water outside interviews, but the idea travels. Whenever a result is capped by the weaker of two ends and grows as the ends move apart, you can start at the extremes and give up the weaker side. Think of picking two points on a line where the bottleneck times the distance is what you want to maximise. Treat that as an analogy for the technique, not a recipe from a specific production system.

Which earlier posts in the series should you read?

Start with the two pointer posts, since they lead straight into today’s problem:

Then, if you want the earlier building blocks, read Day 1, Two Sum for the classic pair sum with a hash map and Day 2, Best Time to Buy and Sell Stock, which tracks the best answer so far in one pass, exactly like best in Container With Most Water. Days 3 to 5 cover Contains Duplicate, Valid Anagram and Group Anagrams for the hashing toolkit. Next up we move on to the sliding window pattern.

Frequently asked questions

What is the time complexity of Container With Most Water?

The two pointer solution runs in O(n) time and O(1) space. The brute force solution that checks every pair takes O(n²) time.

Why do we move the shorter wall in Container With Most Water?

The water level is capped by the shorter wall. Moving the taller wall only shrinks the width while the cap stays the same, so only moving the shorter wall can lead to a bigger area.

Do we need to sort the array for this problem?

No. The distance between walls depends on their original positions, so sorting would give wrong answers.

What if both walls have the same height?

You can move either pointer. Any container using one of them with a wall in between would be narrower and still capped by that same height, so nothing better is lost.

How is this different from Trapping Rain Water?

Container With Most Water picks only two walls and ignores everything between them. Trapping Rain Water adds up the water trapped above every bar, so it needs running max heights from both sides.

Content Protection by DMCA.com
Spread the love
Scroll to Top
×