Total Rainwater Trapped Across an Elevation Map
Solve this Problemheight where each value is the height of a unit-width bar standing at that position. After it rains, water settles in the dips between bars — compute the total volume of water trapped across the whole map.
Try to avoid two extra O(n) arrays for the left/right running maximums — a two-pointer sweep from both ends can get you there in O(1) extra space.
Test Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ height.length ≤ 2 × 10⁴ - ◆
0 ≤ height[i] ≤ 10⁵
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
| 1 | class Solution { |
| 2 | public int totalRainwaterTrapped(int[] height) { |
| 3 | int left = 0, right = height.length - 1; |
| 4 | int leftMax = 0, rightMax = 0; |
| 5 | int total = 0; |
| 6 | while (left < right) { |
| 7 | if (height[left] <= height[right]) { |
| 8 | leftMax = Math.max(leftMax, height[left]); |
| 9 | total += leftMax - height[left]; |
| 10 | left++; |
| 11 | } else { |
| 12 | rightMax = Math.max(rightMax, height[right]); |
| 13 | total += rightMax - height[right]; |
| 14 | right--; |
| 15 | } |
| 16 | } |
| 17 | return total; |
| 18 | } |
| 19 | } |
| 20 |
06000left starts at index 0, right at index 6. leftMax, rightMax, and total all start at 0.
Approach & Solutions
Brute Force — Scan Both Sides for Every Bar
BruteFor every bar, the water sitting above it is capped by the shorter of the tallest wall to its left and the tallest wall to its right. Find those two walls by scanning outward from that bar in each direction, then add min(leftMax, rightMax) - height[i] to the running total (it never goes negative, since leftMax and rightMax both include the bar itself). Repeating the two scans for every index costs O(n²).
O(n²)O(1)1class Solution {
2 public int totalRainwaterTrapped(int[] height) {
3 int total = 0;
4 for (int i = 0; i < height.length; i++) {
5 int leftMax = 0, rightMax = 0;
6 for (int j = 0; j <= i; j++) leftMax = Math.max(leftMax, height[j]);
7 for (int j = i; j < height.length; j++) rightMax = Math.max(rightMax, height[j]);
8 total += Math.min(leftMax, rightMax) - height[i];
9 }
10 return total;
11 }
12}Better — Precompute Left/Right Max Arrays
BetterPrecompute two helper arrays in two clean linear passes: leftMax[i] holds the tallest bar from the start up through i, and rightMax[i] holds the tallest bar from i through the end. With both ready, a third pass adds min(leftMax[i], rightMax[i]) - height[i] at every index. No repeated inner scans like the brute force, but it costs O(n) extra space for the two helper arrays — space the two-pointer version below doesn't need.
O(n)O(n)1class Solution {
2 public int totalRainwaterTrapped(int[] height) {
3 int n = height.length;
4 int[] leftMax = new int[n];
5 int[] rightMax = new int[n];
6 leftMax[0] = height[0];
7 for (int i = 1; i < n; i++) {
8 leftMax[i] = Math.max(leftMax[i - 1], height[i]);
9 }
10 rightMax[n - 1] = height[n - 1];
11 for (int i = n - 2; i >= 0; i--) {
12 rightMax[i] = Math.max(rightMax[i + 1], height[i]);
13 }
14 int total = 0;
15 for (int i = 0; i < n; i++) {
16 total += Math.min(leftMax[i], rightMax[i]) - height[i];
17 }
18 return total;
19 }
20}Optimal — Two Pointers with Running Maxes
OptimalWalk inward from both ends at once, tracking the tallest wall seen so far from the left (leftMax) and from the right (rightMax). Whichever side currently has the shorter running max is the side whose water level is already fully decided — that bar's cap can't come from further away on the other side, since the current far wall is at least as tall as the near one. So process that side: add its trapped water and step it inward. One pass, no extra arrays.
O(n)O(1) extra1class Solution {
2 public int totalRainwaterTrapped(int[] height) {
3 int left = 0, right = height.length - 1;
4 int leftMax = 0, rightMax = 0;
5 int total = 0;
6 while (left < right) {
7 if (height[left] <= height[right]) {
8 leftMax = Math.max(leftMax, height[left]);
9 total += leftMax - height[left];
10 left++;
11 } else {
12 rightMax = Math.max(rightMax, height[right]);
13 total += rightMax - height[right];
14 right--;
15 }
16 }
17 return total;
18 }
19}