Run your code 2 more times to open the solutions. The idea sticks better after an attempt. Container With Most Water in Python
2 reference approaches in Python, from brute force to the one to reach for. Compare them with yours.
Try every pair i < j: the water is the distance j - i times the shorter wall, min(height[i], height[j]). Keep the best one. With fewer than two walls the inner loop never runs and the answer stays 0.
def max_area(height: list[int]) -> int:
best = 0
n = len(height)
for i in range(n):
for j in range(i + 1, n):
area = (j - i) * min(height[i], height[j])
if area > best:
best = area
return best
Start with the widest container, left = 0 and right = len(height) - 1. The shorter of the two walls caps every container it can still be part of, and any of those is narrower, so it can never beat the area you just measured: drop it by moving that pointer inward. Each step discards one wall, so the loop runs at most n - 1 times with no extra memory.
def max_area(height: list[int]) -> int:
left, right = 0, len(height) - 1
best = 0
while left < right:
h = min(height[left], height[right])
best = max(best, (right - left) * h)
if height[left] < height[right]:
left += 1
else:
right -= 1
return best
Container With Most Water in JavaScript
2 reference approaches in JavaScript, from brute force to the one to reach for. Compare them with yours.
Two for loops visit every pair i < j. The water between them is the distance j - i times Math.min(height[i], height[j]), and best keeps the largest. An empty or one-wall array skips the inner loop and returns 0.
function maxArea(height) {
let best = 0;
for (let i = 0; i < height.length; i++) {
for (let j = i + 1; j < height.length; j++) {
best = Math.max(best, (j - i) * Math.min(height[i], height[j]));
}
}
return best;
}
left starts at the first wall and right at the last, the widest container there is. Measure it, then move the pointer at the shorter wall one step inward: every other container that wall could form is narrower and no taller, so it can be discarded. The pointers meet after at most n - 1 steps, using constant extra space.
function maxArea(height) {
let left = 0;
let right = height.length - 1;
let best = 0;
while (left < right) {
const h = Math.min(height[left], height[right]);
best = Math.max(best, (right - left) * h);
if (height[left] < height[right]) left++;
else right--;
}
return best;
}
Container With Most Water in TypeScript
2 reference approaches in TypeScript, from brute force to the one to reach for. Compare them with yours.
Check every pair i < j and keep the largest (j - i) * Math.min(height[i], height[j]). It is O(n²) but needs nothing beyond the best counter.
function maxArea(height: number[]): number {
let best = 0;
for (let i = 0; i < height.length; i++) {
for (let j = i + 1; j < height.length; j++) {
best = Math.max(best, (j - i) * Math.min(height[i], height[j]));
}
}
return best;
}
Start at both ends, the widest container. After measuring it, move the pointer at the shorter wall inward: that wall limits every container it is part of, and the rest are all narrower, so none of them can do better. One pass, two indices, no extra memory.
function maxArea(height: number[]): number {
let left = 0;
let right = height.length - 1;
let best = 0;
while (left < right) {
const h = Math.min(height[left], height[right]);
best = Math.max(best, (right - left) * h);
if (height[left] < height[right]) left++;
else right--;
}
return best;
}
Container With Most Water in Java
2 reference approaches in Java, from brute force to the one to reach for. Compare them with yours.
The outer index i picks the left wall and the inner index j every wall to its right. The water is (j - i) * Math.min(height[i], height[j]), and Math.max keeps the best so far. Arrays shorter than two never enter the inner loop, so the method returns 0.
import java.util.*;
public class Main {
static int maxArea(int[] height) {
int best = 0;
for (int i = 0; i < height.length; i++) {
for (int j = i + 1; j < height.length; j++) {
best = Math.max(best, (j - i) * Math.min(height[i], height[j]));
}
}
return best;
}
}
Two indices start at the ends of the array, the widest container. After each measurement the index at the shorter wall moves one step inward: every other container that wall could form is narrower and no taller, so none of them can beat the current one. The loop ends when the indices meet, after at most n - 1 steps and with two int variables of extra space.
import java.util.*;
public class Main {
static int maxArea(int[] height) {
int left = 0, right = height.length - 1;
int best = 0;
while (left < right) {
int h = Math.min(height[left], height[right]);
best = Math.max(best, (right - left) * h);
if (height[left] < height[right]) {
left++;
} else {
right--;
}
}
return best;
}
}
Container With Most Water in Go
2 reference approaches in Go, from brute force to the one to reach for. Compare them with yours.
for i := range height picks the left wall and the inner three-clause loop every wall to its right. Since Go 1.21, min and max are built in, so the area is simply (j - i) * min(height[i], height[j]). An empty or one-element slice returns 0.
package main
func maxArea(height []int) int {
best := 0
for i := range height {
for j := i + 1; j < len(height); j++ {
best = max(best, (j-i)*min(height[i], height[j]))
}
}
return best
}
left and right start at both ends, the widest container. After measuring it, the index at the shorter wall moves inward, because every other container that wall could form is narrower and no taller. The loop runs until the indices meet: O(n) time, two integers of extra space.
package main
func maxArea(height []int) int {
left, right := 0, len(height)-1
best := 0
for left < right {
h := min(height[left], height[right])
best = max(best, (right-left)*h)
if height[left] < height[right] {
left++
} else {
right--
}
}
return best
}
Container With Most Water in C#
2 reference approaches in C#, from brute force to the one to reach for. Compare them with yours.
Two nested loops try every pair i < j. The water between them is (j - i) * Math.Min(height[i], height[j]), and Math.Max keeps the largest. Arrays with fewer than two walls return 0.
using System;
using System.Collections.Generic;
using System.Linq;
public class Solution
{
public static int MaxArea(int[] height)
{
int best = 0;
for (int i = 0; i < height.Length; i++)
{
for (int j = i + 1; j < height.Length; j++)
{
best = Math.Max(best, (j - i) * Math.Min(height[i], height[j]));
}
}
return best;
}
}
Start with left at the first wall and right at the last. Record the area, then move the index at the shorter wall one step inward: that wall caps every container it can still form, and those are all narrower, so none can win. The indices meet after at most n - 1 steps with constant extra space.
using System;
using System.Collections.Generic;
using System.Linq;
public class Solution
{
public static int MaxArea(int[] height)
{
int left = 0, right = height.Length - 1;
int best = 0;
while (left < right)
{
int h = Math.Min(height[left], height[right]);
best = Math.Max(best, (right - left) * h);
if (height[left] < height[right]) left++;
else right--;
}
return best;
}
}
Container With Most Water in C++
2 reference approaches in C++, from brute force to the one to reach for. Compare them with yours.
Try every pair i < j and keep the largest (j - i) * min(height[i], height[j]). Taking height by reference avoids copying the vector, and casting size() to int keeps the comparisons signed.
#include <algorithm>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;
class Solution {
public:
int maxArea(vector<int>& height) {
int n = (int)height.size();
int best = 0;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
best = max(best, (j - i) * min(height[i], height[j]));
}
}
return best;
}
};
left and right start at both ends, the widest container. After each measurement the index at the shorter wall moves inward, because that wall caps every narrower container it could still form. The loop stops when the indices meet: O(n) time and two ints of extra space.
#include <algorithm>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;
class Solution {
public:
int maxArea(vector<int>& height) {
int left = 0, right = (int)height.size() - 1;
int best = 0;
while (left < right) {
int h = min(height[left], height[right]);
best = max(best, (right - left) * h);
if (height[left] < height[right]) left++;
else right--;
}
return best;
}
};
Container With Most Water in C
2 reference approaches in C, from brute force to the one to reach for. Compare them with yours.
Try every pair i < j: the water is j - i times the shorter wall. C has no min in the standard library, so a small static helper stands in. With a heightSize of 0 or 1 the inner loop never runs and the answer stays 0; no memory is allocated.
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
static int min_int(int a, int b) { return a < b ? a : b; }
int maxArea(int* height, int heightSize) {
int best = 0;
for (int i = 0; i < heightSize; i++) {
for (int j = i + 1; j < heightSize; j++) {
int area = (j - i) * min_int(height[i], height[j]);
if (area > best) best = area;
}
}
return best;
}
Start with the widest container, left = 0 and right = heightSize - 1. The shorter wall caps every narrower container it could still form, so none of them can beat the area just measured: move that pointer inward. The indices are signed ints, so an empty array gives right = -1 and the loop simply never starts.
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
int maxArea(int* height, int heightSize) {
int left = 0, right = heightSize - 1;
int best = 0;
while (left < right) {
int h = height[left] < height[right] ? height[left] : height[right];
int area = (right - left) * h;
if (area > best) best = area;
if (height[left] < height[right]) {
left++;
} else {
right--;
}
}
return best;
}
Container With Most Water in Kotlin
2 reference approaches in Kotlin, from brute force to the one to reach for. Compare them with yours.
Try every pair i < j with height.indices and i + 1 until height.size: the water is (j - i) * minOf(height[i], height[j]), and maxOf keeps the best. An IntArray with fewer than two walls never enters the inner loop, so the answer stays 0.
class Solution {
fun maxArea(height: IntArray): Int {
var best = 0
for (i in height.indices) {
for (j in i + 1 until height.size) {
best = maxOf(best, (j - i) * minOf(height[i], height[j]))
}
}
return best
}
}
Start with the widest container, left = 0 and right = height.lastIndex. The shorter wall caps every narrower container it could still form, so none of them can beat the area just measured: move that pointer inward. lastIndex is -1 for an empty array, so the loop never starts.
class Solution {
fun maxArea(height: IntArray): Int {
var left = 0
var right = height.lastIndex
var best = 0
while (left < right) {
best = maxOf(best, (right - left) * minOf(height[left], height[right]))
if (height[left] < height[right]) left++ else right--
}
return best
}
}
Container With Most Water in Rust
2 reference approaches in Rust, from brute force to the one to reach for. Compare them with yours.
Try every pair i < j. Indices are usize, so the width j - i is cast to i32 before it multiplies the shorter wall, height[i].min(height[j]). For an empty or one-wall vector the inner range is empty and the answer stays 0.
impl Solution {
pub fn max_area(height: Vec<i32>) -> i32 {
let n = height.len();
let mut best = 0;
for i in 0..n {
for j in i + 1..n {
let area = (j - i) as i32 * height[i].min(height[j]);
best = best.max(area);
}
}
best
}
}
Start with the widest container and move the pointer at the shorter wall inward: that wall caps every narrower container it could still form, so none can beat the area just measured. The right index starts at height.len().saturating_sub(1), so an empty vector gives 0 instead of a usize underflow panic, and the loop never starts.
impl Solution {
pub fn max_area(height: Vec<i32>) -> i32 {
let (mut left, mut right) = (0, height.len().saturating_sub(1));
let mut best = 0;
while left < right {
let h = height[left].min(height[right]);
best = best.max((right - left) as i32 * h);
if height[left] < height[right] {
left += 1;
} else {
right -= 1;
}
}
best
}
}
Container With Most Water in Swift
2 reference approaches in Swift, from brute force to the one to reach for. Compare them with yours.
Try every pair i < j: the water is (j - i) * min(height[i], height[j]), and the global max keeps the best. A Swift range with a lower bound above its upper bound traps, so the inner loop uses stride(from: i + 1, to: n, by: 1), which is simply empty when i + 1 > n.
class Solution {
func maxArea(_ height: [Int]) -> Int {
let n = height.count
var best = 0
for i in 0..<n {
for j in stride(from: i + 1, to: n, by: 1) {
best = max(best, (j - i) * min(height[i], height[j]))
}
}
return best
}
}
Start with the widest container, left = 0 and right = height.count - 1. The shorter wall caps every narrower container it could still form, so none can beat the area just measured: move that pointer inward. Swift's Int is signed, so an empty array gives right = -1 and the loop never starts.
class Solution {
func maxArea(_ height: [Int]) -> Int {
var left = 0
var right = height.count - 1
var best = 0
while left < right {
best = max(best, (right - left) * min(height[left], height[right]))
if height[left] < height[right] {
left += 1
} else {
right -= 1
}
}
return best
}
}
Container With Most Water in PHP
2 reference approaches in PHP, from brute force to the one to reach for. Compare them with yours.
Try every pair $i < $j: the water is ($j - $i) times the shorter wall. The count is read once into $n, and a plain comparison stands in for min and max, which matters in an interpreted loop of about a million pairs.
<?php
class Solution {
/**
* @param int[] $height
* @return int
*/
function maxArea(array $height): int {
$n = count($height);
$best = 0;
for ($i = 0; $i < $n; $i++) {
$hi = $height[$i];
for ($j = $i + 1; $j < $n; $j++) {
$h = $hi < $height[$j] ? $hi : $height[$j];
$area = ($j - $i) * $h;
if ($area > $best) {
$best = $area;
}
}
}
return $best;
}
}
Start with the widest container, $left = 0 and $right = count($height) - 1. The shorter wall caps every narrower container it could still form, so none can beat the area just measured: move that pointer inward. An empty array gives $right = -1 and the loop never starts.
<?php
class Solution {
/**
* @param int[] $height
* @return int
*/
function maxArea(array $height): int {
$left = 0;
$right = count($height) - 1;
$best = 0;
while ($left < $right) {
$best = max($best, ($right - $left) * min($height[$left], $height[$right]));
if ($height[$left] < $height[$right]) {
$left++;
} else {
$right--;
}
}
return $best;
}
}
Container With Most Water in Ruby
2 reference approaches in Ruby, from brute force to the one to reach for. Compare them with yours.
Try every pair i < j: the water is (j - i) * [height[i], height[j]].min, and the best one is kept. The inner range (i + 1)...n is empty on the last pass and for fewer than two walls, so the answer stays 0.
# @param {Integer[]} height
# @return {Integer}
def max_area(height)
n = height.length
best = 0
(0...n).each do |i|
hi = height[i]
((i + 1)...n).each do |j|
area = (j - i) * [hi, height[j]].min
best = area if area > best
end
end
best
end
Start with the widest container, left = 0 and right = height.length - 1. The shorter wall caps every narrower container it could still form, so none can beat the area just measured: move that pointer inward. An empty array gives right = -1, so the while loop never starts.
# @param {Integer[]} height
# @return {Integer}
def max_area(height)
left = 0
right = height.length - 1
best = 0
while left < right
area = (right - left) * [height[left], height[right]].min
best = area if area > best
if height[left] < height[right]
left += 1
else
right -= 1
end
end
best
end
Container With Most Water in Dart
2 reference approaches in Dart, from brute force to the one to reach for. Compare them with yours.
Try every pair i < j: the water is (j - i) * min(height[i], height[j]), with min and max from dart:math. With fewer than two walls the inner loop never runs and the answer stays 0.
import 'dart:math';
class Solution {
int maxArea(List<int> height) {
final n = height.length;
var best = 0;
for (var i = 0; i < n; i++) {
for (var j = i + 1; j < n; j++) {
best = max(best, (j - i) * min(height[i], height[j]));
}
}
return best;
}
}
Start with the widest container, left = 0 and right = height.length - 1. The shorter wall caps every narrower container it could still form, so none can beat the area just measured: move that pointer inward. An empty list gives right = -1 and the loop never starts.
import 'dart:math';
class Solution {
int maxArea(List<int> height) {
var left = 0;
var right = height.length - 1;
var best = 0;
while (left < right) {
best = max(best, (right - left) * min(height[left], height[right]));
if (height[left] < height[right]) {
left++;
} else {
right--;
}
}
return best;
}
}
Container With Most Water in Scala
2 reference approaches in Scala, from brute force to the one to reach for. Compare them with yours.
Try every pair i < j in one for with two generators, and keep the best (j - i) * math.min(height(i), height(j)) in a var. Nothing returns from inside the loop, so no boundary is needed; fewer than two walls leave the answer at 0.
object Solution {
def maxArea(height: Array[Int]): Int = {
var best = 0
for (i <- height.indices; j <- i + 1 until height.length) {
best = math.max(best, (j - i) * math.min(height(i), height(j)))
}
best
}
}
Start with the widest container, left = 0 and right = height.length - 1, and step with a while loop. The shorter wall caps every narrower container it could still form, so none can beat the area just measured: move that pointer inward. An empty array gives right = -1 and the loop never starts.
object Solution {
def maxArea(height: Array[Int]): Int = {
var left = 0
var right = height.length - 1
var best = 0
while (left < right) {
best = math.max(best, (right - left) * math.min(height(left), height(right)))
if (height(left) < height(right)) left += 1 else right -= 1
}
best
}
}
FAQ for Python
Why is it safe to move the pointer at the shorter wall?
Say height[left] <= height[right]. Every container that still uses left pairs it with a wall between the pointers, so it is narrower than the current one and no taller than height[left]. None of them can beat the area just recorded, so left can be dropped without missing the answer.
What happens when both walls have the same height?
Move either one. Both walls cap every narrower container at that same height, so no container that keeps one of them can win; the code moves right in the else branch and still finds the answer.
Can I write the brute force with itertools.combinations?
Yes: max(((j - i) * min(height[i], height[j]) for i, j in combinations(range(len(height)), 2)), default=0). It is still O(n²), and default=0 covers inputs with fewer than two walls, where max of an empty generator would raise ValueError.
Why not just pick the two tallest walls?
Width counts as much as height. In [4, 1, 10, 10, 1, 4] the two 10s sit side by side and hold 10, while the 4s at the ends hold 5 × 4 = 20. The two pointers weigh both, because they start wide and only give up width when it cannot help.
Is this the same as trapping rain water?
No. Here you pick two walls and the walls between them are ignored. Trapping rain water sums the water above every position, held in by the tallest wall on each side, so the walls in between matter there.
FAQ for JavaScript
Why is it safe to move the pointer at the shorter wall?
If height[left] <= height[right], every container that keeps left uses a wall between the pointers: it is narrower than the current one and capped at height[left]. None of them can beat the area just recorded, so left++ loses nothing.
What does the code return for an empty array?
right starts at -1, so left < right is false right away and the function returns 0. A single wall gives left === right === 0 and the same 0.
Can I find the answer with Math.max(...array)?
Only as a last step, and only for small inputs: building every area into an array and spreading it into Math.max is still O(n²), and spreading a very large array can throw a RangeError because each element becomes a call argument. Keeping a running best avoids both.
Why not pick the two tallest walls?
Width matters as much as height. For [4, 1, 10, 10, 1, 4] the two 10s hold only 1 * 10 = 10, but the 4s at the ends hold 5 * 4 = 20.
Can the area overflow in JavaScript?
Not here. Numbers are doubles and stay exact up to Number.MAX_SAFE_INTEGER; the largest area these constraints allow is 1,499 × 10,000, far below that.
FAQ for TypeScript
Why is it safe to move the pointer at the shorter wall?
With height[left] <= height[right], any other container that uses left is narrower than the current one and still capped at height[left], so its area cannot be larger. Dropping left skips only containers that cannot win.
Should the parameter be readonly number[]?
It can be: function maxArea(height: readonly number[]): number documents that the function only reads the array, and the compiler rejects an accidental height[i] = 0 or height.sort(). The tests pass either way.
What about equal walls at both ends?
Moving either pointer is correct, because both walls cap every narrower container at the same height. The else branch moves right on a tie.
Why not pick the two tallest walls?
Distance counts too. In [4, 1, 10, 10, 1, 4] the 10s hold 1 * 10 = 10, while the outer 4s hold 5 * 4 = 20.
Does TypeScript make the code any slower?
No. The types are erased when the code is compiled, so the loop runs as plain JavaScript. They only help before the run, for example by flagging a function that forgets to return a number on some path.
FAQ for Java
Why is it safe to move the pointer at the shorter wall?
Suppose height[left] <= height[right]. Any container that keeps left pairs it with a wall between the two indices, so it is narrower and still no taller than height[left]. Its area cannot beat the one just recorded, so left++ throws away only losing pairs.
Can the area overflow an int?
Not within these constraints: the largest area is 1,499 × 10,000, about 15 million, far below Integer.MAX_VALUE. With widths and heights near 10⁵ and 10⁹ the product would wrap silently, so you would compute it as (long) (right - left) * h and return a long.
What happens on an empty array?
right starts at -1, the while condition fails at once and the method returns 0. No index is ever read, so there is no ArrayIndexOutOfBoundsException.
Is a stream version worth it for the brute force?
It reads well, IntStream.range(0, n).flatMap(i -> IntStream.range(i + 1, n).map(j -> (j - i) * Math.min(height[i], height[j]))).max().orElse(0), but it is still O(n²) and slower than the plain loops because of the lambda calls. orElse(0) handles the empty case.
Why not take the two tallest walls?
Width counts as much as height. In {4, 1, 10, 10, 1, 4} the 10s are neighbours and hold 10, while the 4s at the ends hold 5 * 4 = 20.
FAQ for Go
Why is it safe to move the pointer at the shorter wall?
If height[left] <= height[right], every container that keeps left uses a wall between the two indices, so it is narrower and still capped at height[left]. None of them can beat the area just measured, so left++ skips only losers.
Do I need to write my own min and max helpers?
Not since Go 1.21, which made min and max built-in functions for any ordered type. On older toolchains you would write func min(a, b int) int { if a < b { return a }; return b }; math.Min works only on float64.
What happens with an empty slice?
len(height)-1 is -1, so left < right is false at once and the function returns 0 without indexing. A nil slice behaves the same way, since len of nil is 0.
Can the area overflow?
Go int is 64 bits on the usual platforms, and the largest area here is about 15 million, so there is no risk. If you switched to int32 for memory, the product of a large width and height could wrap silently.
Why not pick the two tallest walls?
Width matters as much as height. In []int{4, 1, 10, 10, 1, 4} the 10s are neighbours and hold 10, while the 4s at the ends hold 5 * 4 = 20.
FAQ for C#
Why is it safe to move the pointer at the shorter wall?
When height[left] <= height[right], every other container that uses left is narrower than the current one and no taller than height[left], so its area cannot be larger. Moving left discards only containers that cannot win.
Can the multiplication overflow an int?
Not here: the largest area these constraints allow is 1,499 × 10,000, about 15 million. In an unchecked context a larger product would wrap silently; wrap it in checked(...) to get an OverflowException, or compute it as a long.
Is there a LINQ one-liner for the brute force?
Enumerable.Range(0, n).SelectMany(i => Enumerable.Range(i + 1, n - i - 1), (i, j) => (j - i) * Math.Min(height[i], height[j])).DefaultIfEmpty(0).Max() works, but it is still O(n²) and allocates an enumerator per row. DefaultIfEmpty(0) stops Max from throwing on fewer than two walls.
What happens with an empty array?
right starts at -1, the loop condition is false immediately, and the method returns 0 without reading an element, so there is no IndexOutOfRangeException.
Why not pick the two tallest walls?
Width counts as much as height. In { 4, 1, 10, 10, 1, 4 } the 10s are neighbours and hold 10, while the 4s at the ends hold 5 * 4 = 20.
FAQ for C++
Why is it safe to move the pointer at the shorter wall?
If height[left] <= height[right], every container that keeps left pairs it with a wall between the indices, so it is narrower and still capped at height[left]. None can beat the area just recorded, so left++ loses nothing.
Why cast height.size() to int before subtracting 1?
size() returns an unsigned size_t. On an empty vector height.size() - 1 wraps around to a huge number, and height[right] would then read far out of bounds. Casting first gives -1, so the loop never runs and the function returns 0.
Can the area overflow an int?
Not within these constraints: the largest area is 1,499 × 10,000, about 15 million. Signed overflow is undefined behaviour in C++, so for larger inputs compute (long long)(right - left) * h.
Which header provides min and max?
<algorithm>. std::min and std::max need both arguments of the same type, so max(best, (long long)x) fails to compile when best is an int; cast both sides or keep them the same type.
Why not pick the two tallest walls?
Width counts as much as height. In {4, 1, 10, 10, 1, 4} the 10s are neighbours and hold 10, while the 4s at the ends hold 5 * 4 = 20.
FAQ for C
Is it safe to compute heightSize - 1 when the array is empty?
Yes, because heightSize is a signed int: 0 - 1 is -1, left < right is false and the loop never reads height, which may be NULL here. With a size_t length the same subtraction would wrap to a huge value, so keep indices signed or check heightSize < 2 first.
Why is it safe to move the pointer at the shorter wall?
Say height[left] <= height[right]. Every container that still uses left pairs it with a wall between the pointers, so it is narrower than the current one and no taller than height[left]. None of them can beat the area just recorded, so left can be dropped.
Can the area overflow an int?
Not within these bounds: at most 1499 * 10000, about 1.5·10⁷, far below INT_MAX. Signed overflow is undefined behaviour in C, so for widths and heights near the int range multiply in long long, as in (long long)(right - left) * h.
Why a static min_int function instead of a MIN macro?
A macro such as #define MIN(a, b) ((a) < (b) ? (a) : (b)) evaluates one argument twice, which bites with side effects like MIN(x, height[i++]). A static function evaluates each argument once, is type-checked, and the compiler inlines it anyway.
Why does this function need no malloc or Note comment?
It returns a single int by value, so there is nothing for the caller to free and no *returnSize to set. The malloc rule and its note apply only when the result is an array or a string.
FAQ for Kotlin
Why is it safe to move the pointer at the shorter wall?
Say height[left] <= height[right]. Every container that still uses left pairs it with a wall between the pointers, so it is narrower than the current one and no taller than height[left]. None of them can beat the area just recorded, so left can be dropped without missing the answer.
What is lastIndex on an empty IntArray?
-1, since it is defined as size - 1. That makes left < right false straight away and the function returns 0 without touching the array, so no extra guard is needed for empty or single-wall input.
Can I write the brute force with ranges and maxOrNull?
Yes: height.indices.flatMap { i -> (i + 1 until height.size).map { j -> (j - i) * minOf(height[i], height[j]) } }.maxOrNull() ?: 0. It builds a list of about 1.1 million boxed areas for the largest input, so the plain loops are faster and allocate nothing.
Why IntArray instead of List<Int>?
IntArray maps to a primitive int[] on the JVM, so height[i] reads an unboxed value. A List<Int> stores boxed Integer objects, which costs memory and an unboxing on every read in the O(n²) loop.
What happens when both walls have the same height?
Move either one. Both walls cap every narrower container at that same height, so no container that keeps one of them can win; the code moves right in the else branch and still finds the answer.
FAQ for Rust
Why not write height.len() - 1 for the right pointer?
len() is a usize, and 0usize - 1 panics with "attempt to subtract with overflow" in a debug build (and wraps to usize::MAX in release). The empty vector is a real input here, so saturating_sub(1) clamps it to 0 and the loop condition left < right stops at once.
Can right -= 1 underflow inside the loop?
No. The loop only runs while left < right, so right is at least 1 whenever it is decremented. The only place an underflow could happen is the initial len() - 1, which saturating_sub already covers.
Can I write the brute force with iterators?
Yes: (0..n).flat_map(|i| (i + 1..n).map(move |j| (j - i) as i32 * height[i].min(height[j]))).max().unwrap_or(0). It is still O(n²); unwrap_or(0) covers fewer than two walls, where max returns None. Borrow height as &height first if the closure complains about moving it.
Why cast the width with as i32 instead of the height to usize?
The function returns i32, so multiplying in i32 avoids a second cast at the end. The width is at most 1,499, which always fits; the product stays under 1.5·10⁷, so even the debug build overflow check never fires.
Why is it safe to move the pointer at the shorter wall?
Say height[left] <= height[right]. Every container that still uses left pairs it with a wall between the pointers, so it is narrower than the current one and no taller than height[left]. None of them can beat the area just recorded, so left can be dropped.
FAQ for Swift
Why stride instead of (i + 1)..<n in the brute force?
Here i + 1 never exceeds n, so (i + 1)..<n would work too; it is just empty on the last pass. A range whose lower bound is above its upper bound traps with "Range requires lowerBound <= upperBound", though, so stride(from:to:by:) is the habit that never crashes when the bounds can cross.
Why is it safe to move the pointer at the shorter wall?
Say height[left] <= height[right]. Every container that still uses left pairs it with a wall between the pointers, so it is narrower than the current one and no taller than height[left]. None of them can beat the area just recorded, so left can be dropped without missing the answer.
Can the multiplication overflow Int?
Int is 64-bit on every current Swift platform, and the largest area here is under 1.5·10⁷. Swift traps on overflow rather than wrapping, so an overflow would crash loudly; &* is the wrapping operator if you ever need it.
Do I need import Foundation for min and max?
No. min, max and stride are in the Swift standard library. Leaving out import Foundation keeps each Run about 1.5 s faster on this lane.
Is the O(n²) brute force fast enough in a debug build?
For this size bound, yes: 1,500 walls are about 1.1 million pairs, which the unoptimised build with its bounds and overflow checks finishes in roughly 150 ms. A chain of map and max() per index would allocate an array on every pass, so plain loops are the faster way to write it here.
FAQ for PHP
Why is it safe to move the pointer at the shorter wall?
Say $height[$left] <= $height[$right]. Every container that still uses $left pairs it with a wall between the pointers, so it is narrower than the current one and no taller than $height[$left]. None of them can beat the area just recorded, so $left can be dropped without missing the answer.
Why avoid min and max in the brute force loop?
They are function calls, and the largest input runs the inner loop about 1.1 million times. A ternary and an if skip the call overhead, which is noticeable in an interpreted loop; in the O(n) two-pointer version the calls are cheap enough to keep.
Does count($height) cost anything inside the loop condition?
count on an array is O(1), since PHP stores the element count, but it is still a call on every iteration. Reading it once into $n before the loops is the common habit and keeps the condition a plain comparison.
Can the area overflow a PHP int?
No. PHP integers are 64-bit on the usual builds and the largest area here is under 1.5·10⁷. Past PHP_INT_MAX an integer product turns into a float, which the : int return type then rejects with a TypeError.
Why not just pick the two tallest walls?
Width counts as much as height. In [4, 1, 10, 10, 1, 4] the two 10s sit side by side and hold 10, while the 4s at the ends hold 5 × 4 = 20. The two pointers weigh both, because they start wide and only give up width when it cannot help.
FAQ for Ruby
Does [a, b].min allocate an array on every pair?
No. Since Ruby 2.4 the VM compiles a literal [a, b].min or [a, b].max to a special instruction that compares the values without building the array, so it is as fast as a < b ? a : b and reads better.
Why is it safe to move the pointer at the shorter wall?
Say height[left] <= height[right]. Every container that still uses left pairs it with a wall between the pointers, so it is narrower than the current one and no taller than height[left]. None of them can beat the area just recorded, so left can be dropped without missing the answer.
Can I write the brute force with combination?
Yes: (0...height.length).to_a.combination(2).map { |i, j| (j - i) * [height[i], height[j]].min }.max || 0. It is still O(n²) but builds about 1.1 million pair arrays for the largest input, so the nested ranges are several times faster. || 0 covers fewer than two walls, where max returns nil.
What does height[-1] return, and does it matter here?
A negative index counts from the end, so height[-1] is the last wall and on an empty array it returns nil. The loop never reads height[right] when right is -1, because left < right is already false, so the negative start is harmless.
Is this the same as trapping rain water?
No. Here you pick two walls and the walls between them are ignored. Trapping rain water sums the water above every position, held in by the tallest wall on each side, so the walls in between matter there.
FAQ for Dart
Where do min and max come from in Dart?
They are top-level generic functions in dart:math, so the file starts with import 'dart:math';. Without it, min is undefined; a.compareTo(b) or a ternary works too, but min reads closest to the formula.
Why is it safe to move the pointer at the shorter wall?
Say height[left] <= height[right]. Every container that still uses left pairs it with a wall between the pointers, so it is narrower than the current one and no taller than height[left]. None of them can beat the area just recorded, so left can be dropped without missing the answer.
Can I write the brute force with collection methods?
Yes, with Iterable.generate and expand: Iterable.generate(n, (i) => Iterable.generate(n - i - 1, (k) => (k + 1) * min(height[i], height[i + k + 1]))).expand((e) => e).fold(0, max). It is still O(n²) and fold(0, max) covers fewer than two walls, but the plain loops are easier to read.
Can the int multiplication overflow?
Not here. On the Dart VM an int is a 64-bit integer and the largest area is under 1.5·10⁷. Compiled to JavaScript, int is a double that stays exact up to 2⁵³, which is also far above this bound.
What happens when both walls have the same height?
Move either one. Both walls cap every narrower container at that same height, so no container that keeps one of them can win; the code moves right in the else branch and still finds the answer.
FAQ for Scala
Why is it safe to move the pointer at the shorter wall?
Say height(left) <= height(right). Every container that still uses left pairs it with a wall between the pointers, so it is narrower than the current one and no taller than height(left). None of them can beat the area just recorded, so left can be dropped without missing the answer.
Can I write the brute force without a var?
Yes: height.indices.iterator.flatMap(i => (i + 1 until height.length).iterator.map(j => (j - i) * math.min(height(i), height(j)))).maxOption.getOrElse(0). The iterators keep it lazy, so no collection of 1.1 million areas is built, and getOrElse(0) covers fewer than two walls.
Could the two-pointer loop be a tail-recursive function instead?
Yes: a local @annotation.tailrec def go(l: Int, r: Int, best: Int): Int that returns best when l >= r and otherwise calls itself with one pointer moved. The compiler turns it into a loop, so it is as fast as the while and has no mutable state.
Why math.min instead of height(i) min height(j)?
Both work: a min b is a method on Int through RichInt, and math.min is the plain static call. In a hot O(n²) loop math.min avoids relying on the compiler to optimise the implicit wrapper away.
Why does the first case take longer than the rest?
The JVM loads and compiles the code on the first call, which costs a few hundred milliseconds before the JIT warms up. The later cases, including the largest, run on already compiled code, so their times reflect the algorithm.
Keep going
Daily Temperatures30 / 40 · Monotonic stack · MediumTry Container With Most Water in Python (Container With Most Water in Python), JavaScript (Container With Most Water in JavaScript), TypeScript (Container With Most Water in TypeScript), Java (Container With Most Water in Java), Go (Container With Most Water in Go), C++ (Container With Most Water in C++), C (Container With Most Water in C), Kotlin (Container With Most Water in Kotlin), Rust (Container With Most Water in Rust), Swift (Container With Most Water in Swift), PHP (Container With Most Water in PHP), Ruby (Container With Most Water in Ruby), Dart (Container With Most Water in Dart) or Scala (Container With Most Water in Scala) instead.