Trapping Rain Water Problem in DSA Go - Time & Space Complexity
We want to understand how the time needed to solve the Trapping Rain Water problem changes as the input size grows.
Specifically, how the number of operations depends on the number of bars in the elevation map.
Analyze the time complexity of the following Go code that calculates trapped rain water.
func trap(height []int) int {
n := len(height)
left, right := 0, n-1
leftMax, rightMax := 0, 0
water := 0
for left <= right {
if height[left] < height[right] {
if height[left] > leftMax {
leftMax = height[left]
} else {
water += leftMax - height[left]
}
left++
} else {
if height[right] > rightMax {
rightMax = height[right]
} else {
water += rightMax - height[right]
}
right--
}
}
return water
}
This code uses two pointers moving inward to calculate how much water is trapped between bars.
Look for loops or repeated steps in the code.
- Primary operation: The single for-loop that moves two pointers from both ends towards the center.
- How many times: The loop runs at most
ntimes, wherenis the number of bars.
As the number of bars increases, the loop runs once per bar.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 steps |
| 100 | About 100 steps |
| 1000 | About 1000 steps |
Pattern observation: The number of steps grows linearly with input size.
Time Complexity: O(n)
This means the time to solve the problem grows directly in proportion to the number of bars.
[X] Wrong: "Because there are two pointers, the time is doubled or quadratic."
[OK] Correct: Both pointers move inward without repeating positions, so total steps are still proportional to n, not nΒ².
Understanding this linear time approach shows you can optimize problems by clever pointer use instead of nested loops, a valuable skill in interviews.
"What if we used a nested loop to check water trapped at each bar? How would the time complexity change?"
Practice
Solution
Step 1: Understand the problem context
The problem gives an array representing heights of bars and asks how much water can be trapped between them after rain.Step 2: Identify the goal
The goal is to calculate the total volume of trapped water, not just heights or counts.Final Answer:
The total amount of water trapped between bars -> Option CQuick Check:
Trapping Rain Water = Total trapped water [OK]
- Confusing trapped water with bar heights
- Counting bars instead of water volume
- Ignoring gaps between bars
Solution
Step 1: Recall Go slice initialization syntax
In Go, slices are initialized with []int{values}, arrays with [size]int{values}.Step 2: Identify correct slice syntax
heights := []int{4, 2, 0, 3, 2, 5} uses []int{...} which is correct for a slice. heights := [6]int{4, 2, 0, 3, 2, 5} is an array, also valid but less flexible.Final Answer:
heights := []int{4, 2, 0, 3, 2, 5} -> Option DQuick Check:
Slice syntax = []int{...} [OK]
- Using int[] like in other languages
- Trying to use new keyword for slices
- Confusing arrays and slices syntax
package main
import "fmt"
func trap(height []int) int {
left, right := 0, len(height)-1
leftMax, rightMax := 0, 0
water := 0
for left < right {
if height[left] < height[right] {
if height[left] >= leftMax {
leftMax = height[left]
} else {
water += leftMax - height[left]
}
left++
} else {
if height[right] >= rightMax {
rightMax = height[right]
} else {
water += rightMax - height[right]
}
right--
}
}
return water
}
func main() {
fmt.Println(trap([]int{0,1,0,2,1,0,1,3,2,1,2,1}))
}Solution
Step 1: Understand two-pointer approach
The code uses two pointers moving inward, tracking max heights on left and right to calculate trapped water.Step 2: Trace the example input
For input [0,1,0,2,1,0,1,3,2,1,2,1], the trapped water calculated by this method is 6 units.Final Answer:
6 -> Option AQuick Check:
Two-pointer trap water = 6 [OK]
- Not updating max heights correctly
- Adding negative water amounts
- Confusing left and right pointer moves
func trap(height []int) int {
left, right := 0, len(height)-1
leftMax, rightMax := 0, 0
water := 0
for left <= right {
if height[left] < height[right] {
if height[left] > leftMax {
leftMax = height[left]
} else {
water += leftMax - height[left]
}
left++
} else {
if height[right] > rightMax {
rightMax = height[right]
} else {
water += rightMax - height[right]
}
right--
}
}
return water
}Solution
Step 1: Analyze loop condition impact
The loop uses 'left <= right', which causes double counting when left == right.Step 2: Fix loop condition
Changing to 'left < right' prevents overlap and corrects water calculation.Final Answer:
Change loop condition to 'left < right' instead of 'left <= right' -> Option BQuick Check:
Loop condition fix = 'left < right' [OK]
- Using <= causes double counting
- Changing comparison operators incorrectly
- Incorrect pointer initialization
[5, 2, 1, 2, 1, 5], what is the total trapped rain water? Use the two-pointer approach to solve.Solution
Step 1: Initialize pointers and max heights
left=0, right=5, leftMax=0, rightMax=0, water=0.Step 2: Move pointers inward calculating trapped water
- left=0 (height=5) >= leftMax(0), leftMax=5, left++ - left=1 (2) < right=5 (5), height[left]Final Answer:
10 -> Option AQuick Check:
Two-pointer sum water = 10 [OK]
- Adding water twice for same positions
- Not updating max heights correctly
- Stopping loop too early
Ready to prove it?
Pass the test and this pattern moves unknown
