Trapping Rain Water Problem in DSA C - 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 steps grows when we have more bars in the elevation map.
Analyze the time complexity of the following code snippet.
int trap(int* height, int heightSize) {
int left = 0, right = heightSize - 1;
int leftMax = 0, rightMax = 0;
int water = 0;
while (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 calculates how much water can be trapped between bars represented by an array of heights.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: A single while loop that moves two pointers from both ends towards the center.
- How many times: The loop runs until the two pointers meet, so roughly once per element in the array.
As the number of bars increases, the loop runs once for each bar, so the steps grow directly with input size.
| 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 as input size grows.
Time Complexity: O(n)
This means the time to solve the problem grows in direct proportion to the number of bars.
[X] Wrong: "Because there are two pointers, the time is O(n²)."
[OK] Correct: Each pointer moves only forward and never goes back, so together they make at most n steps total, not n times n.
Understanding this linear time solution shows you can optimize problems by clever pointer use instead of nested loops, a valuable skill in interviews.
"What if we used nested loops to check every pair of bars? How would the time complexity change?"
Practice
Solution
Step 1: Understand the problem context
The problem involves an array representing heights of bars where water can be trapped between them.Step 2: Identify the goal
The goal is to calculate how much water can be trapped after raining between these bars.Final Answer:
The total amount of water trapped between the bars after raining -> Option DQuick Check:
Trapping Rain Water = Total trapped water [OK]
- Confusing trapped water with bar heights
- Calculating max or min height instead of trapped water
- Ignoring the space between bars
Solution
Step 1: Check array declaration syntax in C
Arrays are declared with type, name, and initializer list in braces {}.Step 2: Validate each option
int heights[] = {4, 2, 0, 3, 2, 5}; uses correct syntax: int heights[] = {4, 2, 0, 3, 2, 5}; Options A, B, D have syntax errors.Final Answer:
int heights[] = {4, 2, 0, 3, 2, 5}; -> Option AQuick Check:
Correct C array syntax = int heights[] = {4, 2, 0, 3, 2, 5}; [OK]
- Using parentheses () instead of braces {}
- Missing array size or incorrect initializer syntax
- Using square brackets [] for initialization
int heights[] = {3, 0, 2, 0, 4};
int n = 5;
int left_max[5], right_max[5];
int water = 0;
// Calculate left max
left_max[0] = heights[0];
for (int i = 1; i < n; i++) {
left_max[i] = (heights[i] > left_max[i-1]) ? heights[i] : left_max[i-1];
}
// Calculate right max
right_max[n-1] = heights[n-1];
for (int i = n-2; i >= 0; i--) {
right_max[i] = (heights[i] > right_max[i+1]) ? heights[i] : right_max[i+1];
}
// Calculate trapped water
for (int i = 0; i < n; i++) {
water += (left_max[i] < right_max[i] ? left_max[i] : right_max[i]) - heights[i];
}
printf("%d\n", water);Solution
Step 1: Calculate left_max and right_max arrays
left_max = [3, 3, 3, 3, 4], right_max = [4, 4, 4, 4, 4]Step 2: Calculate trapped water at each index
Water trapped = sum of min(left_max[i], right_max[i]) - heights[i] = (3-3)+(3-0)+(3-2)+(3-0)+(4-4) = 0+3+1+3+0 = 7Final Answer:
7 -> Option CQuick Check:
Sum trapped water = 7 [OK]
- Mixing up left_max and right_max arrays
- Forgetting to subtract heights from min of max arrays
- Off-by-one errors in loops
int trap(int* height, int heightSize) {
int left_max[heightSize];
int right_max[heightSize];
int water = 0;
left_max[0] = height[0];
for (int i = 1; i < heightSize; i++) {
left_max[i] = height[i] > left_max[i-1] ? height[i] : left_max[i-1];
}
right_max[heightSize-1] = height[heightSize-1];
for (int i = heightSize-2; i >= 0; i--) {
right_max[i] = height[i] > right_max[i+1] ? height[i] : right_max[i+1];
}
for (int i = 0; i < heightSize; i++) {
water += (left_max[i] < right_max[i] ? left_max[i] : right_max[i]) - height[i];
}
return water;
}Solution
Step 1: Analyze array declarations
The code uses int left_max[heightSize]; and int right_max[heightSize]; which are variable length arrays (VLA).Step 2: Understand VLA support in C
VLAs are optional in C11 and may not be supported by all compilers, causing portability issues or errors.Final Answer:
Using variable length arrays (VLA) which may not be supported -> Option BQuick Check:
VLAs may cause errors = Using variable length arrays (VLA) which may not be supported [OK]
- Assuming VLAs always work in all C compilers
- Ignoring compiler warnings about VLAs
- Confusing VLA issue with logic errors
{0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}, what is the total trapped rain water using the two-pointer approach in C?Solution
Step 1: Understand two-pointer approach
Use two pointers left and right starting at ends, track left_max and right_max, move pointers inward calculating trapped water.Step 2: Dry run the array
Heights: [0,1,0,2,1,0,1,3,2,1,2,1] Water trapped = 6 units after calculating min(left_max, right_max) - height at each step.Final Answer:
6 -> Option AQuick Check:
Two-pointer trapped water = 6 [OK]
- Not updating left_max and right_max correctly
- Moving pointers incorrectly causing missed water
- Confusing two-pointer with prefix arrays method
Ready to prove it?
Pass the test and this pattern moves unknown
