Close Menu
    Code and Debug
    • Home
    • Our Courses
    • Blog
    • About Us
    • Contact Us
    Facebook X (Twitter) Instagram YouTube WhatsApp
    • Home
    • Our Courses
    • Blog
    • About Us
    • Contact Us
    Facebook Instagram YouTube LinkedIn WhatsApp
    Code and Debug – BlogCode and Debug – Blog
    Code and Debug – BlogCode and Debug – Blog
    Home»Data Structures & Algorithms»Trapping Rain Water | Leetcode 42 | Brute, Better and Optimal Solution using Stack
    Data Structures & Algorithms

    Trapping Rain Water | Leetcode 42 | Brute, Better and Optimal Solution using Stack

    Anirudh KhuranaBy Anirudh Khurana11 August 2025No Comments6 Mins Read
    Share Facebook Twitter Pinterest LinkedIn Tumblr Reddit Telegram Email
    Featured image of a question to solve trapping rain water
    Share
    Facebook Twitter LinkedIn Pinterest Email

    Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it can trap after raining.

    Here’s the [Problem Link] to begin with.

    Example 1:

    Input: height = [0,1,0,2,1,0,1,3,2,1,2,1]
    Output: 6
    Explanation: The above elevation map (black section) is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped.

    Example 2:

    Input: height = [4,2,0,3,2,5]
    Output: 9

    Constraints:

    • n == height.length
    • 1 <= n <= 2 * 104
    • 0 <= height[i] <= 105
    Contents:
     [show]
    • Brute Solution: Prefix and Suffix Arrays
      • Intuition and Approach
      • Code Implementation
      • Code Explanation
      • Time and Space Complexity
      • Conclusion
    • Better Solution: One Suffix Array + Running Left Max
      • Intuition and Approach
      • Code Implementation
      • Code Explanation
      • Time and Space Complexity
      • Conclusion
    • Optimal Solution: Two-Pointer Technique
      • Intuition and Approach
      • Code Implementation
      • Code Explanation
      • Time and Space Complexity
      • Conclusion
    • Final Takeaways

    Brute Solution: Prefix and Suffix Arrays

    Intuition and Approach

    • For each position i, find:
      • The tallest bar on the left up to i (call it prefixMax[i]).
      • The tallest bar on the right from i to the end (call it suffixMax[i]).
    • Water at position i is limited by the shorter side among these two maxima.
    • So, water at i = min(prefixMax[i], suffixMax[i]) − height[i].
    • Add this for all positions to get the total trapped water.

    Why it works:

    • Water can only stand up to the height of the shorter wall among left and right sides.
    • Precomputing both sides for every index makes calculation straightforward.

    Code Implementation

    class Solution:
        def trap(self, height: List[int]) -> int:
            if not height or len(height) < 3:
                return 0
    
            n = len(height)
    
            # Initialize prefixMax and suffixMax arrays.
            prefixMax = [0] * n
            suffixMax =  * n
    
            # Fill the prefixMax array (tallest from the left up to i).
            prefixMax = height
            for i in range(1, n):
                prefixMax[i] = max(prefixMax[i - 1], height[i])
    
            # Fill the suffixMax array (tallest from the right from i to end).
            suffixMax[n - 1] = height[n - 1]
            for i in range(n - 2, -1, -1):
                suffixMax[i] = max(suffixMax[i + 1], height[i])
    
            # Calculate the total water trapped.
            trapped_water = 0
            for i in range(n):
                # Water at i is the difference between the limiting wall and bar height.
                trapped_water += min(prefixMax[i], suffixMax[i]) - height[i]
    
            return trapped_water

    Code Explanation

    • We first compute the tallest bar to the left for each index (prefixMax).
    • Then we compute the tallest bar to the right for each index (suffixMax).
    • For each index, the water is the smaller of these two heights minus the actual bar height.
    • Summing across all indices gives total trapped water.

    Time and Space Complexity

    • Precise: Time O(n + n + n) = O(3n), Space O(2n).
    • Simplified: Time O(n), Space O(n).

    Conclusion

    • Very easy to understand and implement.
    • Uses extra memory for two arrays, but logic is simple and reliable.

    Better Solution: One Suffix Array + Running Left Max

    Intuition and Approach

    • We can avoid storing both arrays.
    • Precompute only right-side maxima in an array (rightMax).
    • As we scan from left to right, keep a running leftMax.
    • Water at i = min(leftMax, rightMax[i]) − height[i].

    Why it works:

    • You still need both left and right maxima for each position.
    • The left maximum can be kept as a single number updated as we move forward.

    Code Implementation

    from typing import List
    
    class Solution:
        def trap(self, height: List[int]) -> int:
            n = len(height)
            if n < 3:
                return 0
    
            # rightMax[i] = max(height[i..n-1])
            rightMax = [0] * n
            rightMax[-1] = height[-1]
            for i in range(n - 2, -1, -1):
                rightMax[i] = max(rightMax[i + 1], height[i])
    
            trapped = 0
            leftMax = 0
            for i in range(n):
                # Update leftMax up to current i
                leftMax = max(leftMax, height[i])
                # Water at i is limited by the lower of leftMax and rightMax[i]
                trapped += min(leftMax, rightMax[i]) - height[i]
    
            return trapped

    Code Explanation

    • We compute rightMax once by scanning from right to left.
    • We maintain leftMax on the fly while scanning from left to right.
    • At each index, the smaller of leftMax and rightMax[i] determines the water level.

    Time and Space Complexity

    • Precise: Time O(n + n) = O(2n), Space O(n).
    • Simplified: Time O(n), Space O(n).

    Conclusion

    • Same core idea as Brute, but saves memory by avoiding the full left array.
    • A nice balance between simplicity and space saving.

    Optimal Solution: Two-Pointer Technique

    Intuition and Approach

    • The side with the smaller current height limits the water.
    • Use two pointers:
      • left at the start, right at the end.
      • leftMax stores the tallest seen so far from the left.
      • rightMax stores the tallest seen so far from the right.
    • Move the pointer on the smaller side inward:
      • If height[left] < height[right]:
        • If height[left] < leftMax, water += leftMax − height[left].
        • Else update leftMax.
        • Move left forward.
      • Else do the symmetric steps on the right.

    Why it works:

    • The water at the smaller side depends only on that side’s max, not on the far side.
    • This lets us decide locally which pointer to move and how much water to add, in one pass.

    Code Implementation

    class Solution:
        def trap(self, height: List[int]) -> int:
            # Edge case: If the height list is empty or has less than 3 elements, no water can be trapped.
            if not height or len(height) < 3:
                return 0
    
            # Initialize two pointers and variables to keep track of maximum heights.
            left, right = 0, len(height) - 1
            leftMax, rightMax = 0, 0
            trapped_water = 0
    
            # Traverse the elevation map using two pointers.
            while left < right:
                # Compare the heights at both pointers.
                if height[left] < height[right]:
                    # Calculate water trapped at the left index.
                    if height[left] >= leftMax:
                        leftMax = height[left]  # Update leftMax.
                    else:
                        trapped_water += leftMax - height[left]  # Water trapped.
                    left += 1  # Move left pointer to the right.
                else:
                    # Calculate water trapped at the right index.
                    if height[right] >= rightMax:
                        rightMax = height[right]  # Update rightMax.
                    else:
                        trapped_water += rightMax - height[right]  # Water trapped.
                    right -= 1  # Move right pointer to the left.
    
            return trapped_water

    Code Explanation

    • We always process the side that is shorter because that side limits the water level there.
    • If the current bar on that side is lower than the recorded max for that side, the difference is the water trapped on top of that bar.
    • This avoids building any extra arrays and finishes in one pass.

    Time and Space Complexity

    • Precise: Time O(n), Space O(1).
    • Simplified: Fastest and most memory-efficient.

    Conclusion

    • Best approach for interviews and production use.
    • Minimal memory, single scan, clean logic once you know the insight.

    Final Takeaways

    • Water at a position depends on the shorter of the tallest bars to its left and right.
    • Brute: Two arrays (easiest to grasp).
    • Better: One array + running left max (saves memory).
    • Optimal: Two pointers (fastest and least memory).
    Join our Advance DSA COURSE

    For any changes to the article, kindly email at code@codeanddebug.in or contact us at +91-9712928220.

    Hard Stack and Queues
    Share. Facebook Twitter Pinterest LinkedIn Tumblr Email
    Previous ArticleNext Greater Element II | Leetcode 503 | Imaginary List Optimal Solution
    Next Article Cherry Pickup II | Leetcode 1463 | Solved using Dynamic Programming
    Anirudh Khurana
    • Website

    Anirudh Khurana is the founder of Code and Debug, an Indian EdTech platform that helps students and working professionals crack coding interviews and move into data and AI roles. He teaches DSA, Python, SQL, data engineering and machine learning through live bootcamps and his YouTube channel, Code and Debug, which has over 50,000 subscribers. Every guide on this blog is written or reviewed by him and tested with real code.

    Related Posts

    Data Structures & Algorithms

    DSA Interview Cheat Sheet: All Patterns You Need to Know

    4 April 2026
    Data Structures & Algorithms

    Symmetric Tree | Leetcode 101 | Recursive DFS Approach

    2 September 2025
    Data Structures & Algorithms

    Binary Tree Right Side View | Leetcode 199 | BFS and DFS Approaches

    2 September 2025
    Add A Comment
    Leave A Reply Cancel Reply

    Categories
    • AI & Machine Learning (4)
    • Data Structures & Algorithms (241)
      • Beginner (82)
      • Expert (52)
      • Intermediate (106)
    • Pandas (1)
    • Python (1)
    • Resume (1)
    • SQL (1)
    Recent Posts

    Confusion Matrix in Machine Learning: An Interactive Guide

    21 October 2026

    100 SQL Interview Questions with Queries and Answers (Freshers to Experienced)

    17 October 2026

    Logistic Regression in Machine Learning: Explained Visually (with Python)

    17 October 2026

    Linear Regression in Machine Learning: Explained Visually (with Python)

    17 October 2026

    100 Python Interview Questions and Answers for Freshers and Experienced (Free PDF)

    17 October 2026
    Facebook Instagram YouTube LinkedIn WhatsApp
    © 2025 Code and Debug. All rights reserved.

    Type above and press Enter to search. Press Esc to cancel.