Two pointers · Opposite ends
height of length n. Line i is a vertical line from (i, 0) up to (i, height[i]). Pick two lines. With the x-axis they form a container, and the container can't be tilted. Return the most water a container can hold.
i < j. The lines in between do not matter.So one pair holds min(height[i], height[j]) × (j − i). Wide pairs help, and tall pairs help, but they pull against each other.
Measure every pair with that formula and keep the largest.
Time: O(n²). There are n × (n − 1) / 2 pairs, which is about 5 × 10⁹ for n = 10⁵. Space: O(1).
All the time goes into measuring pairs. So the question is: which pairs can we skip without measuring them?
The first and the last line form the widest pair, and every other pair is narrower. So another pair can only win by being taller. But a pair's height is capped by its shorter line, and that is the line to watch.
Measure the pair, and call its shorter line lo and the other hi. Any other pair that uses lo has its partner closer than hi. That pair is narrower, and its height is still capped by lo. So it cannot hold more than the pair we just measured.
That means lo is finished. We measure the pair, drop the shorter line and move that pointer inward. On the example, the pair (0, 6) has heights 3 and 4, so line 0 is dropped.
The shorter line would stay in the pair and still cap the height, while the pair gets narrower. We lose width for nothing, and we might throw away the best pair. Equal lines are safe either way, because the argument holds for both.
lo on the first line and hi on the last. Set best = 0.min(height[lo], height[hi]) × (hi − lo) and keep the larger of it and best.best.Pick an input and press Play, or use the arrow keys.
When the two lines are equal, the code drops lo, which is safe. With [1, 1] there is one pair and the answer is 1. On [4, 3, 2, 1, 4] the very first pair is the best, 4 × 4 = 16, and the rest are only checked.
best. Nothing grows with the input.[3, 9, 2, 5, 8, 8, 4] we just measured (1, 5), heights 9 and 8. Which pointer moves, and where to?Answerhi moves, from 5 to 4. The right line (8) is the lower one, so it is dropped.
AnswerThe taller line may be part of the best pair. At (1, 6) moving both goes to (2, 5), which skips (1, 5), the pair with 32.
[4, 3, 2, 1, 4], what is the answer and how many pairs does the code measure?Answer16, from the first pair (0, 4). It measures 4 pairs: 16, 9, 4 and 1. That is n − 1, not all 10 pairs.
Open one to see an answer you could say out loud.
What they are checkingWhether you can prove the greedy step, or only repeat "move the shorter one".
A strong answerEach time I drop a line, every pair I give up that includes it is narrower and capped by that same shorter line, so it cannot beat the pair I just measured. I only skip pairs that cannot win, and the pointers stop only when they meet.
What they are checkingWhether you can adapt the two-pointer idea. This is Trapping Rain Water.
A strong answerThe water above a position fills up to the lower of the tallest line on its left and the tallest on its right, minus its own height. Keep two pointers and the tallest line seen from each side, and always move the pointer whose side has the lower tallest line, because that side already decides its level. O(n) time, O(1) space.
What they are checkingWhether you check the largest value before you trust the code.
A strong answerThe biggest area is 10,000 × 99,999, about 109. A 32-bit integer holds about 2.1 × 109, so it fits, with little room. If the limits grew I would use a 64-bit number. In Python it does not matter.
min).When it does not apply: if a pair's value is not capped by one of its ends (for example height[i] + height[j]), dropping an end proves nothing, and this argument fails.