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, we ask: How does the number of steps grow when the height array gets bigger?
Analyze the time complexity of the following code snippet.
int trap(vector<int>& height) {
int n = height.size();
vector<int> leftMax(n), rightMax(n);
leftMax[0] = height[0];
for (int i = 1; i < n; i++) {
leftMax[i] = max(leftMax[i-1], height[i]);
}
rightMax[n-1] = height[n-1];
for (int i = n-2; i >= 0; i--) {
rightMax[i] = max(rightMax[i+1], height[i]);
}
int water = 0;
for (int i = 0; i < n; i++) {
water += min(leftMax[i], rightMax[i]) - height[i];
}
return water;
}
This code calculates how much water can be trapped after raining given an array of heights.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Three separate loops each running through the height array once.
- How many times: Each loop runs exactly n times, where n is the size of the height array.
As the input size n grows, the number of operations grows roughly in a straight line with n.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 30 steps (3 loops x 10) |
| 100 | About 300 steps (3 loops x 100) |
| 1000 | About 3000 steps (3 loops x 1000) |
Pattern observation: The steps increase directly with input size, tripled due to three loops but still linear.
Time Complexity: O(n)
This means the time to solve the problem grows in a straight line with the size of the input array.
[X] Wrong: "Because there are nested max and min operations, the time complexity is quadratic O(n²)."
[OK] Correct: Each max or min is done inside a single loop, not nested loops. So the operations are done one after another, not multiplied.
Understanding this linear time solution shows you can break down a problem into simple passes over data, a key skill in many coding challenges.
"What if we tried to find trapped water using nested loops checking every pair of bars? 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 it rains.Step 2: Identify the goal
The goal is to calculate the total trapped water volume, not just heights or counts.Final Answer:
The total amount of water that can be trapped between the bars after raining -> Option AQuick Check:
Trapping rain water = total trapped water [OK]
- Confusing trapped water with highest bar height
- Summing bar heights instead of trapped water
- Counting bars taller than a certain height
Solution
Step 1: Check vector initialization syntax
In C++, std::vector<int> can be initialized with curly braces and values inside, like {0,1,...}.Step 2: Identify correct syntax
std::vector<int> heights = {0,1,0,2,1,0,1,3,2,1,2,1}; uses correct syntax with std::vector<int> and brace initialization.Final Answer:
std::vector<int> heights = {0,1,0,2,1,0,1,3,2,1,2,1}; -> Option BQuick Check:
Correct vector init uses braces and type [OK]
- Omitting std:: before vector
- Using parentheses instead of braces
- Not specifying vector type
std::vector<int> height = {0,1,0,2,1,0,1,3,2,1,2,1};
int n = height.size();
int left_max = 0, right_max = 0, left = 0, right = n - 1, water = 0;
while (left < right) {
if (height[left] < height[right]) {
if (height[left] >= left_max) left_max = height[left];
else water += left_max - height[left];
left++;
} else {
if (height[right] >= right_max) right_max = height[right];
else water += right_max - height[right];
right--;
}
}
std::cout << water << std::endl;Solution
Step 1: Understand two-pointer approach
Two pointers move inward, tracking max heights on left and right, accumulating trapped water where current height is less than max.Step 2: Trace the code logic on given input
For input {0,1,0,2,1,0,1,3,2,1,2,1}, the total trapped water calculated is 6 units.Final Answer:
6 -> Option AQuick Check:
Two-pointer trapped water = 6 [OK]
- Not updating left_max or right_max correctly
- Adding negative water amounts
- Confusing left and right pointer moves
std::vector<int> height = {4,2,0,3,2,5};
int n = height.size();
int left_max = 0, right_max = 0, left = 0, right = n - 1, water = 0;
while (left <= right) {
if (height[left] < height[right]) {
if (height[left] > left_max) left_max = height[left];
else water += left_max - height[left];
left++;
} else {
if (height[right] > right_max) right_max = height[right];
else water += right_max - height[right];
right--;
}
}
std::cout << water << std::endl;Solution
Step 1: Analyze loop condition impact
The loop uses 'left <= right', which causes the middle element to be processed twice, leading to incorrect water calculation.Step 2: Fix loop condition
Changing condition to 'left < right' ensures each element is processed once, preventing double counting.Final Answer:
Change while condition to 'left < right' to avoid double counting -> Option CQuick Check:
Loop condition 'left < right' fixes double count bug [OK]
- Using <= instead of < in while loop
- Not updating max heights correctly
- Assuming no bug without testing
Solution
Step 1: Understand space constraints
Precomputing arrays uses extra space O(n), which is costly for very large inputs.Step 2: Use two-pointer approach for O(1) space
Two pointers from both ends track max heights and calculate trapped water without extra arrays, making it efficient.Final Answer:
Use two pointers from both ends, track max heights, and calculate trapped water on the fly -> Option DQuick Check:
Two-pointer approach = efficient O(1) space [OK]
- Using extra arrays causing high memory use
- Sorting changes bar order, invalid for trapping water
- Recursion adds overhead and complexity
Ready to prove it?
Pass the test and this pattern moves unknown
