Bird
Raised Fist0
DSA C++programming

Trapping Rain Water Problem in DSA C++

Choose your learning style10 modes available
Mental Model
We want to find how much water can be trapped between bars after it rains by looking at the height of bars on both sides.
Analogy: Imagine a row of buildings with different heights. Rainwater collects in the dips between taller buildings, like water filling valleys between hills.
Height bars: 3 0 2 0 4
Visual: 4 |       ↑
        3 | ↑     ↑
        2 | ↑   ↑ ↑
        1 | ↑   ↑ ↑
        0 | ↑ ↑ ↑ ↑ ↑
          0 1 2 3 4  (indexes)
Dry Run Walkthrough
Input: heights: [3, 0, 2, 0, 4]
Goal: Calculate total trapped water between bars
Step 1: Initialize two pointers at start (left=0) and end (right=4), and max heights left_max=0, right_max=0
left=0 (height=3), right=4 (height=4), left_max=0, right_max=0, trapped=0
Why: We start from both ends to compare heights and find trapped water efficiently
Step 2: Since height[left] < height[right], move left pointer to 1 (height=0), update left_max=3
left=1 (height=0), right=4, left_max=3, right_max=0, trapped=3 (3 - 0)
Why: Water trapped at index 1 is left_max - height[1] = 3 - 0 = 3
Step 3: Move left pointer to 2 (height=2), trapped += 3 - 2 = 1
left=2 (height=2), right=4, left_max=3, right_max=0, trapped=4
Why: Water trapped at index 2 is 1 unit
Step 4: Move left pointer to 3 (height=0), trapped += 3 - 0 = 3
left=3 (height=0), right=4, left_max=3, right_max=0, trapped=7
Why: Water trapped at index 3 is 3 units
Step 5: Left pointer reaches 4, stop
left=4, right=4, trapped=7
Why: All positions processed, total trapped water found
Result:
Total trapped water = 7 units
Annotated Code
DSA C++
#include <iostream>
#include <vector>
using namespace std;

int trapRainWater(const vector<int>& height) {
    int left = 0, right = (int)height.size() - 1;
    int left_max = 0, right_max = 0;
    int trapped = 0;
    while (left < right) {
        if (height[left] < height[right]) {
            if (height[left] >= left_max) {
                left_max = height[left];
            } else {
                trapped += left_max - height[left];
            }
            left++;
        } else {
            if (height[right] >= right_max) {
                right_max = height[right];
            } else {
                trapped += right_max - height[right];
            }
            right--;
        }
    }
    return trapped;
}

int main() {
    vector<int> height = {3, 0, 2, 0, 4};
    cout << trapRainWater(height) << "\n";
    return 0;
}
while (left < right) {
loop until pointers meet to process all bars
if (height[left] < height[right]) {
decide which pointer to move based on smaller height
if (height[left] >= left_max) { left_max = height[left]; } else { trapped += left_max - height[left]; }
update left_max or add trapped water at left pointer
left++;
move left pointer forward
if (height[right] >= right_max) { right_max = height[right]; } else { trapped += right_max - height[right]; }
update right_max or add trapped water at right pointer
right--;
move right pointer backward
OutputSuccess
7
Complexity Analysis
Time: O(n) because we traverse the height array once with two pointers
Space: O(1) because we use only a few variables, no extra arrays
vs Alternative: Compared to using extra arrays for left_max and right_max (O(n) space), this two-pointer method is more space efficient
Edge Cases
Empty height array
Returns 0 trapped water since no bars exist
DSA C++
while (left < right) {
All bars same height
No water trapped, returns 0
DSA C++
if (height[left] >= left_max) { left_max = height[left]; } else { trapped += left_max - height[left]; }
Single bar
No water trapped, returns 0
DSA C++
while (left < right) {
When to Use This Pattern
When asked to find how much water is trapped between bars or heights, use the two-pointer approach to efficiently calculate trapped water by comparing left and right max heights.
Common Mistakes
Mistake: Using nested loops to check water trapped at each bar causing O(n^2) time
Fix: Use two pointers moving inward with tracking max heights to achieve O(n) time
Mistake: Not updating left_max or right_max correctly leading to negative trapped water
Fix: Always update max heights before calculating trapped water at current pointer
Summary
Calculates total water trapped between bars after rain using two pointers.
Use when you need to find trapped rainwater efficiently in a height array.
The key insight is to move pointers inward from smaller height side, updating max heights and accumulating trapped water.

Practice

(1/5)
1. What does the Trapping Rain Water problem ask you to find given an array of heights?
easy
A. The total amount of water that can be trapped between the bars after raining
B. The highest bar in the array
C. The number of bars taller than a given height
D. The sum of all bar heights

Solution

  1. 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.
  2. Step 2: Identify the goal

    The goal is to calculate the total trapped water volume, not just heights or counts.
  3. Final Answer:

    The total amount of water that can be trapped between the bars after raining -> Option A
  4. Quick Check:

    Trapping rain water = total trapped water [OK]
Hint: Think of bars as walls holding water in gaps [OK]
Common Mistakes:
  • Confusing trapped water with highest bar height
  • Summing bar heights instead of trapped water
  • Counting bars taller than a certain height
2. Which of the following C++ code snippets correctly initializes a vector named heights with values {0,1,0,2,1,0,1,3,2,1,2,1}?
easy
A. std::vector<int> heights = (0,1,0,2,1,0,1,3,2,1,2,1);
B. std::vector<int> heights = {0,1,0,2,1,0,1,3,2,1,2,1};
C. vector<int> heights(0,1,0,2,1,0,1,3,2,1,2,1);
D. std::vector heights = {0,1,0,2,1,0,1,3,2,1,2,1};

Solution

  1. Step 1: Check vector initialization syntax

    In C++, std::vector<int> can be initialized with curly braces and values inside, like {0,1,...}.
  2. 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.
  3. Final Answer:

    std::vector<int> heights = {0,1,0,2,1,0,1,3,2,1,2,1}; -> Option B
  4. Quick Check:

    Correct vector init uses braces and type [OK]
Hint: Use curly braces {} for vector initialization [OK]
Common Mistakes:
  • Omitting std:: before vector
  • Using parentheses instead of braces
  • Not specifying vector type
3. What is the output of the following C++ code snippet that calculates trapped rain water?
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;
medium
A. 6
B. 5
C. 7
D. 8

Solution

  1. 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.
  2. 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.
  3. Final Answer:

    6 -> Option A
  4. Quick Check:

    Two-pointer trapped water = 6 [OK]
Hint: Use two pointers and track max heights from both ends [OK]
Common Mistakes:
  • Not updating left_max or right_max correctly
  • Adding negative water amounts
  • Confusing left and right pointer moves
4. Identify the bug in this C++ code snippet for trapping rain water and select the fix:
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;
medium
A. Initialize left_max and right_max to height[0] and height[n-1] respectively
B. Use '>=' instead of '>' when updating left_max and right_max
C. Change while condition to 'left < right' to avoid double counting
D. No bug, code is correct

Solution

  1. 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.
  2. Step 2: Fix loop condition

    Changing condition to 'left < right' ensures each element is processed once, preventing double counting.
  3. Final Answer:

    Change while condition to 'left < right' to avoid double counting -> Option C
  4. Quick Check:

    Loop condition 'left < right' fixes double count bug [OK]
Hint: Use strict less than in two-pointer loops [OK]
Common Mistakes:
  • Using <= instead of < in while loop
  • Not updating max heights correctly
  • Assuming no bug without testing
5. Given an array representing heights of bars, how would you modify the standard trapping rain water algorithm to handle very large input efficiently without extra space?
hard
A. Use recursion to calculate trapped water for each bar
B. Precompute left_max and right_max arrays and sum trapped water using extra arrays
C. Sort the array and calculate trapped water based on sorted positions
D. Use two pointers from both ends, track max heights, and calculate trapped water on the fly

Solution

  1. Step 1: Understand space constraints

    Precomputing arrays uses extra space O(n), which is costly for very large inputs.
  2. 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.
  3. Final Answer:

    Use two pointers from both ends, track max heights, and calculate trapped water on the fly -> Option D
  4. Quick Check:

    Two-pointer approach = efficient O(1) space [OK]
Hint: Two pointers save space by avoiding extra arrays [OK]
Common Mistakes:
  • Using extra arrays causing high memory use
  • Sorting changes bar order, invalid for trapping water
  • Recursion adds overhead and complexity
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard