Trapping Rain Water

July 6, 2025

Question

Given an array of non-negative integers where each element represents the height of a bar, compute how much water it can trap after raining.

Water can only be trapped between bars, and it's limited by the height of the shortest bar on either side.

Example

Input: [0, 3, 1, 4, 0, 2, 1, 5, 0, 2, 3]

Output: 15

Explanation: Water is trapped at indices 2 (2), 4 (4), 5 (2), 6 (3), 8 (3), and 9 (1). Total = 2 + 4 + 2 + 3 + 3 + 1 = 15.


Input: [1, 0, 1]

Output: 1

Explanation: 1 unit is trapped at index 1.

Visual

0 1 2 3 4 5 0 1 2 3 4 5 6 7 8 9 10 Total Water Trapped = 15

My Notes

package main

import (
    "fmt"
)

func main() {
    result := trap([]int{0, 3, 1, 4, 0, 2, 1, 5, 0, 2, 3})
    fmt.Println(result)
}

func trap(height []int) int {
    if len(height) < 3 {
        return 0
    }

    left, right, result := make([]int, len(height)), make([]int, len(height)), 0

    left[0] = 0
    for i := 1; i < len(height); i++ {
        if left[i-1] > height[i-1] {
            left[i] = left[i-1]
        } else {
            left[i] = height[i-1]
        }
    }

    right[len(height) - 1] = 0
    for i := len(height) - 2 ; i >= 0; i-- {
        if right[i+1] > height[i+1] {
            right[i] = right[i+1]
        } else {
            right[i] = height[i+1]
        }
    }

    for i := 0; i < len(height); i++ {
        var min int

        if left[i] < right[i] {
            min = left[i]
        } else {
            min = right[i]
        }

        area := min - height[i]

        if area > 0 {
            result += area
        }
    }

    return result
}