Open In App

Trapping Rain Water

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

Given an array of N non-negative integers arr[] representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.

Examples:  

Input: arr[] = {2, 0, 2}
Output: 2
Explanation: The structure is like below.
We can trap 2 units of water in the middle gap.

Input: arr[]   = {3, 0, 2, 0, 4}
Output: 7
Explanation: Structure is like below.
We can trap “3 units” of water between 3 and 2,
“1 unit” on top of bar 2 and “3 units” between 2 and 4.

Input: arr[] = {0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}
Output: 6
Explanation: The structure is like below.
Trap “1 unit” between first 1 and 2, “4 units” between
first 2 and 3 and “1 unit” between second last 1 and last 2

Recommended Practice

Intuition: The basic intuition of the problem is as follows:

  • An element of the array can store water if there are higher bars on the left and the right. 
  • The amount of water to be stored in every position can be found by finding the heights of bars on the left and right sides. 
  • The total amount of water stored is the summation of the water stored in each index.

For example – Consider the array arr[] = {3, 0, 2, 0, 4}
Three units of water can be stored in two indexes 1 and 3, and one unit of water at index 2.
Water stored in each index = 0 + 3 + 1 + 3 + 0 = 7  

Approach 1 (Brute Approach): This approach is the brute approach. The idea is to:

Traverse every array element and find the highest bars on the left and right sides. Take the smaller of two heights. The difference between the smaller height and the height of the current element is the amount of water that can be stored in this array element.

Follow the steps mentioned below to implement the idea:

  • Traverse the array from start to end:
    • For every element: 
      • Traverse the array from start to that index and find the maximum height (a) and 
      • Traverse the array from the current index to the end, and find the maximum height (b).
  • The amount of water that will be stored in this column is min(a,b) – array[i], add this value to the total amount of water stored
  • Print the total amount of water stored.

Below is the implementation of the above approach.

C++




// C++ implementation of the approach
  
#include <bits/stdc++.h>
using namespace std;
  
// Function to return the maximum
// water that can be stored
int maxWater(int arr[], int n)
{
    // To store the maximum water
    // that can be stored
    int res = 0;
  
    // For every element of the array
    for (int i = 1; i < n - 1; i++) {
  
        // Find the maximum element on its left
        int left = arr[i];
        for (int j = 0; j < i; j++)
            left = max(left, arr[j]);
  
        // Find the maximum element on its right
        int right = arr[i];
        for (int j = i + 1; j < n; j++)
            right = max(right, arr[j]);
  
        // Update the maximum water
        res = res + (min(left, right) - arr[i]);
    }
  
    return res;
}
  
// Driver code
int main()
{
    int arr[] = { 0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1 };
    int n = sizeof(arr) / sizeof(arr[0]);
  
    cout << maxWater(arr, n);
  
    return 0;
}


C




// C code to implement the approach
  
#include <stdio.h>
  
// Creating MACRO for finding the maximum number
#define max(x, y) (((x) > (y)) ? (x) : (y))
  
// Creating MACRO for finding the minimum number
#define min(x, y) (((x) < (y)) ? (x) : (y))
  
// Function to return the maximum
// water that can be stored
int maxWater(int arr[], int n)
{
    // To store the maximum water
    int res = 0;
  
    // For every element of the array
    for (int i = 0; i < n; i++) {
  
        // Find the maximum element on its left
        int left = arr[i];
        for (int j = 0; j < i; j++) {
            left = max(left, arr[j]);
        }
  
        // Find the maximum element on its left
        int right = arr[i];
        for (int j = i + 1; j < n; j++) {
            right = max(right, arr[j]);
        }
  
        // Update the result (maximum water)
        res = res + (min(left, right) - arr[i]);
    }
  
    // Return the maximum water
    return res;
}
  
// Driver code
int main()
{
    int arr[] = { 0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1 };
    int n = sizeof(arr) / sizeof(arr[0]);
    printf("%d", maxWater(arr, n));
    return 0;
}
  
// This code is contributed by amnindersingh1414.


Java




// Java code to implement of the approach
  
class GFG {
  
    // Function to return the maximum
    // water that can be stored
    public static int maxWater(int[] arr, int n)
    {
  
        // To store the maximum water
        // that can be stored
        int res = 0;
  
        // For every element of the array
        // except first and last element
        for (int i = 1; i < n - 1; i++) {
  
            // Find maximum element on its left
            int left = arr[i];
            for (int j = 0; j < i; j++) {
                left = Math.max(left, arr[j]);
            }
  
            // Find maximum element on its right
            int right = arr[i];
            for (int j = i + 1; j < n; j++) {
                right = Math.max(right, arr[j]);
            }
  
            // Update maximum water value
            res += Math.min(left, right) - arr[i];
        }
        return res;
    }
  
    // Driver code
    public static void main(String[] args)
    {
        int[] arr = { 0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1 };
        int n = arr.length;
  
        System.out.print(maxWater(arr, n));
    }
}
  
// This code is contributed by Debidutta Rath


Python3




# Python3 implementation of the approach
  
# Function to return the maximum
# water that can be stored
def maxWater(arr, n):
  
    # To store the maximum water
    # that can be stored
    res = 0
  
    # For every element of the array
    for i in range(1, n - 1):
  
        # Find the maximum element on its left
        left = arr[i]
        for j in range(i):
            left = max(left, arr[j])
  
        # Find the maximum element on its right
        right = arr[i]
  
        for j in range(i + 1, n):
            right = max(right, arr[j])
  
        # Update the maximum water
        res = res + (min(left, right) - arr[i])
  
    return res
  
  
# Driver code
if __name__ == "__main__":
  
    arr = [0, 1, 0, 2, 1, 0,
           1, 3, 2, 1, 2, 1]
    n = len(arr)
  
    print(maxWater(arr, n))
  
# This code is contributed by AnkitRai01


C#




// C# implementation of the approach
  
using System;
  
class GFG {
  
    // Function to return the maximum
    // water that can be stored
    public static int maxWater(int[] arr, int n)
    {
  
        // To store the maximum water
        // that can be stored
        int res = 0;
  
        // For every element of the array
        // except first and last element
        for (int i = 1; i < n - 1; i++) {
  
            // Find maximum element on its left
            int left = arr[i];
            for (int j = 0; j < i; j++) {
                left = Math.Max(left, arr[j]);
            }
  
            // Find maximum element on its right
            int right = arr[i];
            for (int j = i + 1; j < n; j++) {
                right = Math.Max(right, arr[j]);
            }
  
            // Update maximum water value
            res += Math.Min(left, right) - arr[i];
        }
        return res;
    }
  
    // Driver code
    public static void Main(String[] args)
    {
        int[] arr = { 0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1 };
        int n = arr.Length;
  
        Console.Write(maxWater(arr, n));
    }
}
  
// This code is contributed by shivanisinghss2110


Javascript




<script>
  
    // Javascript implementation of the approach
      
    // Function to return the maximum
    // water that can be stored
    function maxWater(arr, n)
    {
  
        // To store the maximum water
        // that can be stored
        let res = 0;
  
        // For every element of the array
        // except first and last element
        for(let i = 1; i < n - 1; i++)
        {
  
            // Find maximum element on its left
            let left = arr[i];
            for(let j = 0; j < i; j++)
            {
                left = Math.max(left, arr[j]);
            }
  
            // Find maximum element on its right
            let right = arr[i];
            for(let j = i + 1; j < n; j++)
            {
                right = Math.max(right, arr[j]);
            }
  
            // Update maximum water value
            res += Math.min(left, right) - arr[i];
        }
        return res;
    }
      
    let arr = [ 0, 1, 0, 2, 1, 0,
                1, 3, 2, 1, 2, 1 ];
    let n = arr.length;
   
    document.write(maxWater(arr,n));
      
</script>


Output

6

Complexity Analysis: 

  • Time Complexity: O(N2). There are two nested loops traversing the array.
  • Space Complexity: O(1). No extra space is required.

Approach 2 (Precalculation): This is an efficient solution based on the precalculation concept:

In previous approach, for every element we needed to calculate the highest element on the left and on the right. 

So, to reduce the time complexity: 

  • For every element we can precalculate and store the highest bar on the left and on the right (say stored in arrays left[] and right[]). 
  • Then iterate the array and use the precalculated values to find the amount of water stored in this index, 
    which is the same as ( min(left[i], right[i]) – arr[i] )

Follow the below illustration for a better understanding:

Illustration:

Consider arr[] = {3, 0, 2, 0, 4}

Therefore, left[] = {3, 3, 3, 3, 4} and right[] = {4, 4, 4, 4, 4}
Now consider iterating using i from 0 to end

For i = 0:
        => left[0] = 3, right[0] = 4 and arr[0] = 3
        => Water stored = min(left[0], right[0]) – arr[0] = min(3, 4) – 3 = 3 – 3 = 0
        => Total = 0 + 0 = 0

For i = 1:
        => left[1] = 3, right[1] = 4 and arr[1] = 0
        => Water stored = min(left[1], right[1]) – arr[1] = min(3, 4) – 0 = 3 – 0 = 3
        => Total = 0 + 3 = 3

For i = 2:
        => left[2] = 3, right[2] = 4 and arr[2] = 2
        => Water stored = min(left[2], right[2]) – arr[2] = min(3, 4) – 2 = 3 – 2 = 1
        => Total = 3 + 1 = 4

For i = 3:
        => left[3] = 3, right[3] = 4 and arr[3] = 0
        => Water stored = min(left[3], right[3]) – arr[3] = min(3, 4) – 0 = 3 – 0 = 3
        => Total = 4 + 3 = 7

For i = 4:
        => left[4] = 4, right[4] = 4 and arr[4] = 4
        => Water stored = min(left[4], right[4]) – arr[4] = min(4, 4) – 4 = 4 – 4 = 0
        => Total = 7 + 0 = 7

So total rain water trapped = 7

Follow the steps mentioned below to implement the approach:

  • Create two arrays left[] and right[] of size N. Create a variable (say max) to store the maximum found till a certain index during traversal.
  • Run one loop from start to end: 
    • In each iteration update max and also assign left[i] = max.
  • Run another loop from end to start: 
    • In each iteration update max found till now and also assign right[i] = max.
  • Traverse the array from start to end.
    • The amount of water that will be stored in this column is min(left[i], right[i]) – array[i]
    • Add this value to the total amount of water stored
  • Print the total amount of water stored.

Below is the implementation of the above approach.

C++




// C++ program to find maximum amount of water that can
// be trapped within given set of bars.
#include <bits/stdc++.h>
using namespace std;
  
int findWater(int arr[], int n)
{
    // left[i] contains height of tallest bar to the
    // left of i'th bar including itself
    int left[n];
  
    // Right [i] contains height of tallest bar to
    // the right of ith bar including itself
    int right[n];
  
    // Initialize result
    int water = 0;
  
    // Fill left array
    left[0] = arr[0];
    for (int i = 1; i < n; i++)
        left[i] = max(left[i - 1], arr[i]);
  
    // Fill right array
    right[n - 1] = arr[n - 1];
    for (int i = n - 2; i >= 0; i--)
        right[i] = max(right[i + 1], arr[i]);
  
    // Calculate the accumulated water element by element
    // consider the amount of water on i'th bar, the
    // amount of water accumulated on this particular
    // bar will be equal to min(left[i], right[i]) - arr[i]
    // .
    for (int i = 1; i < n - 1; i++) {
        int var = min(left[i - 1], right[i + 1]);
        if (var > arr[i]) {
            water += var - arr[i];
        }
    }
  
    return water;
}
  
// Driver program
int main()
{
    int arr[] = { 0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1 };
    int n = sizeof(arr) / sizeof(arr[0]);
    cout << findWater(arr, n);
    return 0;
}


C




// Implementation in C of the above approach
  
// Importing the required header files
#include <stdio.h>
  
// Creating MACRO for finding the maximum number
#define max(x, y) (((x) > (y)) ? (x) : (y))
  
// Creating MACRO for finding the minimum number
#define min(x, y) (((x) < (y)) ? (x) : (y))
  
// Function to return the maximum
// water that can be stored
int findWater(int arr[], int n)
{
  
    // left[i] contains height of tallest bar to the
    // left of i'th bar including itself
    int left[n];
  
    // Right [i] contains height of tallest bar to the
    // right of ith bar including itself
    int right[n];
  
    // Initialize result
    int water = 0;
  
    // Fill left array
    left[0] = arr[0];
    for (int i = 1; i < n; i++) {
        left[i] = max(left[i - 1], arr[i]);
    }
  
    // Fill right array
    right[n - 1] = arr[n - 1];
    for (int i = n - 2; i >= 0; i--) {
        right[i] = max(right[i + 1], arr[i]);
    }
  
    // Calculate the accumulated water element by element
    // consider the amount of water on i'th bar, the
    // amount of water accumulated on this particular
    // bar will be equal to min(left[i], right[i]) - arr[i]
    // .
    for (int i = 1; i < n - 1; i++) {
        int var = min(left[i - 1], right[i + 1]);
        if (var > arr[i]) {
            water += var - arr[i];
        }
    }
  
    return water;
}
  
// Driver program
int main()
{
    int arr[] = { 0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1 };
    int n = sizeof(arr) / sizeof(arr[0]);
    printf("%d", findWater(arr, n));
    return 0;
}
  
// This code is contributed by amnindersingh1414.


Java




// Java program to find maximum amount of water that can
// be trapped within given set of bars.
  
class Test {
    static int arr[]
        = new int[] { 0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1 };
  
    // Method for maximum amount of water
    static int findWater(int n)
    {
        // left[i] contains height of tallest bar to the
        // left of i'th bar including itself
        int left[] = new int[n];
  
        // Right [i] contains height of tallest bar to
        // the right of ith bar including itself
        int right[] = new int[n];
  
        // Initialize result
        int water = 0;
  
        // Fill left array
        left[0] = arr[0];
        for (int i = 1; i < n; i++)
            left[i] = Math.max(left[i - 1], arr[i]);
  
        // Fill right array
        right[n - 1] = arr[n - 1];
        for (int i = n - 2; i >= 0; i--)
            right[i] = Math.max(right[i + 1], arr[i]);
  
        // Calculate the accumulated water element by
        // element consider the amount of water on i'th bar,
        // the amount of water accumulated on this
        // particular bar will be equal to min(left[i],
        // right[i]) - arr[i] .
        for (int i = 0; i < n; i++)
            water += Math.min(left[i], right[i]) - arr[i];
  
        return water;
    }
  
    // Driver method to test the above function
    public static void main(String[] args)
    {
  
        System.out.println(findWater(arr.length));
    }
}


Python3




# Python program to find maximum amount of water that can
# be trapped within given set of bars.
  
  
def findWater(arr, n):
  
    # left[i] contains height of tallest bar to the
    # left of i'th bar including itself
    left = [0]*n
  
    # Right [i] contains height of tallest bar to
    # the right of ith bar including itself
    right = [0]*n
  
    # Initialize result
    water = 0
  
    # Fill left array
    left[0] = arr[0]
    for i in range(1, n):
        left[i] = max(left[i-1], arr[i])
  
    # Fill right array
    right[n-1] = arr[n-1]
    for i in range(n-2, -1, -1):
        right[i] = max(right[i + 1], arr[i])
  
    # Calculate the accumulated water element by element
    # consider the amount of water on i'th bar, the
    # amount of water accumulated on this particular
    # bar will be equal to min(left[i], right[i]) - arr[i] .
    for i in range(0, n):
        water += min(left[i], right[i]) - arr[i]
  
    return water
  
  
# Driver program
if __name__ == '__main__':
    arr = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]
    n = len(arr)
    print(findWater(arr, n))
  
# This code is contributed by
# Smitha Dinesh Semwal


C#




// C# program to find maximum amount of water that can
// be trapped within given set of bars.
using System;
  
class Test {
    static int[] arr
        = new int[] { 0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1 };
  
    // Method for maximum amount of water
    static int findWater(int n)
    {
        // left[i] contains height of tallest bar to the
        // left of i'th bar including itself
        int[] left = new int[n];
  
        // Right [i] contains height of tallest bar to
        // the right of ith bar including itself
        int[] right = new int[n];
  
        // Initialize result
        int water = 0;
  
        // Fill left array
        left[0] = arr[0];
        for (int i = 1; i < n; i++)
            left[i] = Math.Max(left[i - 1], arr[i]);
  
        // Fill right array
        right[n - 1] = arr[n - 1];
        for (int i = n - 2; i >= 0; i--)
            right[i] = Math.Max(right[i + 1], arr[i]);
  
        // Calculate the accumulated water element by
        // element consider the amount of water on i'th bar,
        // the amount of water accumulated on this
        // particular bar will be equal to min(left[i],
        // right[i]) - arr[i] .
        for (int i = 0; i < n; i++)
            water += Math.Min(left[i], right[i]) - arr[i];
  
        return water;
    }
  
    // Driver method to test the above function
    public static void Main()
    {
  
        Console.WriteLine(findWater(arr.Length));
    }
}
  
// This code is contributed by vt_m.


PHP




<?php
// PHP program to find maximum
// amount of water that can
// be trapped within given set of bars.
  
function findWater($arr, $n)
{
      
    // left[i] contains height of
    // tallest bar to the
    // left of i'th bar including 
    // itself 
  
    // Right [i] contains height
    // of tallest bar to the right 
    // of ith bar including itself
    // $right[$n];
  
    // Initialize result
    $water = 0;
  
    // Fill left array
    $left[0] = $arr[0];
    for ($i = 1; $i < $n; $i++)
    $left[$i] = max($left[$i - 1],
                        $arr[$i]);
  
    // Fill right array
    $right[$n - 1] = $arr[$n - 1];
    for ($i = $n - 2; $i >= 0; $i--)
    $right[$i] = max($right[$i + 1], 
                           $arr[$i]);
  
    // Calculate the accumulated
    // water element by element
    // consider the amount of 
    // water on i'th bar, the
    // amount of water accumulated
    // on this particular
    // bar will be equal to min(left[i], 
    // right[i]) - arr[i] .
    for ($i = 0; $i < $n; $i++)
    $water += min($left[$i], $right[$i]) 
                             - $arr[$i];
  
    return $water;
}
  
    // Driver program
    $arr = array(0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1);
    $n = sizeof($arr);
    echo findWater($arr, $n);
      
// This code is contributed by ajit
?>


Javascript




<script>
// Javascript program to find maximum amount of water that can
// be trapped within given set of bars.
      
    let arr = [ 0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1 ];
      
    // Method for maximum amount of water
    function findWater(n)
    {
      
        // left[i] contains height of tallest bar to the
        // left of i'th bar including itself
        let left = new Array(n);
   
        // Right [i] contains height of tallest bar to
        // the right of ith bar including itself
        let right = new Array(n);
   
        // Initialize result
        let water = 0;
   
        // Fill left array
        left[0] = arr[0];
        for (let i = 1; i < n; i++)
            left[i] = Math.max(left[i - 1], arr[i]);
   
        // Fill right array
        right[n - 1] = arr[n - 1];
        for (let i = n - 2; i >= 0; i--)
            right[i] = Math.max(right[i + 1], arr[i]);
   
        // Calculate the accumulated water element by element
        // consider the amount of water on i'th bar, the
        // amount of water accumulated on this particular
        // bar will be equal to min(left[i], right[i]) - arr[i] .
        for (let i = 0; i < n; i++)
            water += Math.min(left[i], right[i]) - arr[i];
   
        return water;
    }
      
    // Driver method to test the above function
    document.write(findWater(arr.length));
  
    // This code is contributed by unknown2108
</script>


Output

6

Complexity Analysis:

  • Time Complexity: O(N). Only one traversal of the array is needed, So time Complexity is O(N).
  • Space Complexity: O(N). Two extra arrays are needed, each of size N.

Approach 3 (Using Stack): The idea to solve the problem using stack is as follows:

We can use a stack to track the bars that are bounded by the higher left and right bars. This can be done using only one iteration.

  • For this we will keep pushing elements in stack, until an element with higher value than the stack top is found. This denotes that there is a chance of storing position on the left side of the current element with the current bar being an end.
  • So remove the smaller element on left and find the left bar (which is the current top of stack) and the amount of water stored by the left end bar and the current bar being the right end. Continue this till the stack is not empty or a higher value element is found.

Follow the below illustration for a better understanding.

Illustration:

Consider the array arr[] = {3, 0, 2, 0, 4} and an empty stack st.

For i = 0:
        => The stack is empty. So no elements with higher value on left.
        => Push the index into the stack. st = {0} [to keep track of the distance in between]

For i = 1:
        => arr[1] is less than arr[stack top]. So arr[1] has a higher left bound.
        => Push the index into stack. st = {0, 1}

For i = 2:
        => arr[2] is greater than arr[stack top]. So arr[2] is the higher right bound of current stack top.
        => Calculate the water stored in between the left and right bound of the stack top. 
        => The stack top is the base height in between the left and right bound.
        => Pop the stack top. So st = {0}.
        => Water stored in between when arr[0] and arr[2] are the bound= {min(arr[0], arr[2]) – arr[1]} * (2 – 0 – 1) = 2.
        => arr[0] is greater than arr[2] Push the index into stack. st = {0, 2}.
        => Total water stored = 0 + 2 = 2.

For i = 3:
        => arr[3] is less than arr[2]. So arr[3] has a higher left bound.
        => Push the index into the stack. st = {0, 2, 3}.

For i = 4:
        => arr[4] is greater than arr[stack top]. So arr[4] is the higher right bound of current stack top.
        => Calculate the water stored in same way as for i = 2. The base height is arr[3].
        => Pop the stack top. So st = {0, 2}.
        => Water stored in between when arr[4] and arr[2] are the bound= {min(arr[4], arr[2]) – arr[3]} * (4 – 2 – 1) = 2.
        => arr[4] is greater than arr[2].
        => Pop the stack. st = {0}.
        => Water stored in between arr[0] and arr[4] when arr[2] is the base height = {min(3, 4) – 2} * (4 – 0 – 1) = 3
        => arr[0] less than arr[4]. So pop stack. st = {}.
        => As no element left in the stack push the index. st = {4}.
        => Total water stored = 2 + 2 + 3 = 7.

So the total amount of water stored  = 7.

Follow the steps mentioned below to implement the idea:

  • Loop through the indices of the bar array.
  • For each bar, do the following:
    • Loop while the Stack is not empty and the current bar has a height greater than the top bar of the stack,
      • Store the index of the top bar in pop_height and pop it from the Stack.
      • Find the distance between the left bar(current top) of the popped bar and the current bar.
      • Find the minimum height between the top bar and the current bar.
      • The maximum water that can be trapped is distance * min_height.
      • The water trapped, including the popped bar, is (distance * min_height) – height[pop_height].
      • Add that to the answer.
  • Return the amount received as the total amount of water

Below is the implementation of the above approach.

C++




// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
  
// Function to return the maximum
// water that can be stored
int maxWater(int height[], int n)
{
  
    // Stores the indices of the bars
    stack<int> st;
  
    // Stores the final result
    int ans = 0;
  
    // Loop through the each bar
    for (int i = 0; i < n; i++) {
  
        // Remove bars from the stack
        // until the condition holds
        while ((!st.empty())
               && (height[st.top()] < height[i])) {
  
            // Store the height of the top
            // and pop it.
            int pop_height = height[st.top()];
            st.pop();
  
            // If the stack does not have any
            // bars or the popped bar
            // has no left boundary
            if (st.empty())
                break;
  
            // Get the distance between the
            // left and right boundary of
            // popped bar
            int distance = i - st.top() - 1;
  
            // Calculate the min. height
            int min_height
                = min(height[st.top()], height[i])
                  - pop_height;
  
            ans += distance * min_height;
        }
  
        // If the stack is either empty or
        // height of the current bar is less than
        // or equal to the top bar of stack
        st.push(i);
    }
    return ans;
}
  
// Driver code
int main()
{
  
    int arr[] = { 0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1 };
    int n = sizeof(arr) / sizeof(arr[0]);
  
    cout << maxWater(arr, n);
  
    return 0;
}
  
// The code is contributed by Soumitri Chattopadhyay


Java




import java.io.*;
import java.util.*;
  
// Java implementation of the approach
class GFG {
  
    // Function to return the maximum
    // water that can be stored
    public static int maxWater(int[] height)
    {
        // Stores the indices of the bars
        Stack<Integer> stack = new Stack<>();
  
        // size of the array
        int n = height.length;
  
        // Stores the final result
        int ans = 0;
  
        // Loop through the each bar
        for (int i = 0; i < n; i++) {
  
            // Remove bars from the stack
            // until the condition holds
            while ((!stack.isEmpty())
                   && (height[stack.peek()] < height[i])) {
  
                // store the height of the top
                // and pop it.
                int pop_height = height[stack.peek()];
                stack.pop();
  
                // If the stack does not have any
                // bars or the popped bar
                // has no left boundary
                if (stack.isEmpty())
                    break;
  
                // Get the distance between the
                // left and right boundary of
                // popped bar
                int distance = i - stack.peek() - 1;
  
                // Calculate the min. height
                int min_height
                    = Math.min(height[stack.peek()],
                               height[i])
                      - pop_height;
  
                ans += distance * min_height;
            }
  
            // If the stack is either empty or
            // height of the current bar is less than
            // or equal to the top bar of stack
            stack.push(i);
        }
  
        return ans;
    }
    // Driver code
    public static void main(String[] args)
    {
        int arr[] = { 0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1 };
        System.out.print(maxWater(arr));
    }
}


Python3




# Python implementation of the approach
  
# Function to return the maximum
# water that can be stored
  
  
def maxWater(height):
  
    # Stores the indices of the bars
    stack = []
  
    # size of the array
    n = len(height)
  
    # Stores the final result
    ans = 0
  
    # Loop through the each bar
    for i in range(n):
  
        # Remove bars from the stack
        # until the condition holds
        while(len(stack) != 0 and (height[stack[-1]] < height[i])):
  
            # store the height of the top
            # and pop it.
            pop_height = height[stack[-1]]
            stack.pop()
  
            # If the stack does not have any
            # bars or the popped bar
            # has no left boundary
            if(len(stack) == 0):
                break
  
            # Get the distance between the
            # left and right boundary of
            # popped bar
            distance = i - stack[-1] - 1
  
            # Calculate the min. height
            min_height = min(height[stack[-1]], height[i])-pop_height
  
            ans += distance * min_height
  
        # If the stack is either empty or
        # height of the current bar is less than
        # or equal to the top bar of stack
        stack.append(i)
  
    return ans
  
  
# Driver code
if __name__ == '__main__':
    arr = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]
    print(maxWater(arr))
  
# This code is contributed by rag2127


C#




using System;
using System.Collections;
using System.Collections.Generic;
  
// C# implementation of the approach
class GFG {
  
    // Function to return the maximum
    // water that can be stored
    public static int maxWater(int[] height)
    {
  
        // Stores the indices of the bars
        Stack stack = new Stack();
  
        // size of the array
        int n = height.Length;
  
        // Stores the final result
        int ans = 0;
  
        // Loop through the each bar
        for (int i = 0; i < n; i++) {
  
            // Remove bars from the stack
            // until the condition holds
            while ((stack.Count != 0)
                   && (height[(int)stack.Peek()]
                       < height[i])) {
  
                // store the height of the top
                // and pop it.
                int pop_height = height[(int)stack.Peek()];
                stack.Pop();
  
                // If the stack does not have any
                // bars or the popped bar
                // has no left boundary
                if (stack.Count == 0)
                    break;
  
                // Get the distance between the
                // left and right boundary of
                // popped bar
                int distance = i - (int)stack.Peek() - 1;
  
                // Calculate the min. height
                int min_height
                    = Math.Min(height[(int)stack.Peek()],
                               height[i])
                      - pop_height;
  
                ans += distance * min_height;
            }
  
            // If the stack is either empty or
            // height of the current bar is less than
            // or equal to the top bar of stack
            stack.Push(i);
        }
        return ans;
    }
  
    // Driver code
    public static void Main()
    {
        int[] arr = { 0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1 };
        Console.Write(maxWater(arr));
    }
}
  
// This code is contributed by pratham76.


Javascript




<script>
  
// Python implementation of the approach
  
// Function to return the maximum
// water that can be stored
function maxWater(height){
      
    // Stores the indices of the bars
    let stack = []
      
    // size of the array
    let n = height.length
      
    // Stores the final result
    let ans = 0
      
    // Loop through the each bar
    for(let i=0;i<n;i++){
          
        // Remove bars from the stack
        // until the condition holds
        while(stack.length != 0 && (height[stack[stack.length-1]] < height[i]) ){
              
            // store the height of the top
            // and pop it.
            let pop_height = height[stack.pop()]
              
            // If the stack does not have any
            // bars or the popped bar
            // has no left boundary
            if(stack.length == 0)
                break
              
            // Get the distance between the
            // left and right boundary of
            // popped bar
            let distance = i - stack[stack.length - 1] - 1
              
            // Calculate the min. height
            let min_height =Math.min(height[stack[stack.length - 1]],height[i])-pop_height
              
            ans += distance * min_height
        }
          
        // If the stack is either empty or
        // height of the current bar is less than
        // or equal to the top bar of stack
        stack.push(i)
    }
      
    return ans
}
  
// Driver code
let arr = [ 0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]
document.write(maxWater(arr))
  
// This code is contributed by shinjanpatra
  
</script>


Output

6

Time Complexity: O(N)
Auxiliary Space: O(N)

Approach 4 (Horizontal scan method): The idea is as follows:

  • If max_height is the height of the tallest block, then it will be the maximum possible height for any trapped rainwater. 
  • And if for each unit of height we find the leftmost and the rightmost boundary for that height, we can consider all the blocks in between contain that amount of water. 
  • But this will consider the height of the bars also. So we have to subtract that from the total water trapped.

This can be justified as follows. Say the sections for a certain height is {i1, i2}, {i2, i3}, . . ., {ik-1, ik}
So the water stored in between for a single unit of height is the difference in between the indices
= (i2 – i1 – 1) + (i3 – i2 – 1) + . . . + (ik – ik-1 -1}) = ik – i1 – (k-1) where k is the number of bars in between.

But as we are considering all the blocks in between left and right boundary, it considers all the bars also.
So the trapped water for a single unit becomes (ik – i1 + 1)

Follow the below illustration for a better understanding.

Illustration:

Consider array arr[] = {3, 0, 2, 0, 4}.
max_height = 4 and sum of all blocks = 2 + 3 + 4 = 9.

For height = 1:
        => leftmost boundary = 0 and rightmost boundary = 4.
        => All blocks in between contain 1 height of water. 
        => So amount of water trapped = (4 – 0 + 1) = 5
        => Total trapped water = 0+5 = 5

 For height = 2:
        => leftmost boundary = 0 and rightmost boundary = 4.
        => All blocks in between contain 2 height of water.
        => Earlier we have considered water columns with height 1. So there is increase of 1 unit in height. 
        => So amount of water trapped = (4 – 0 + 1) = 5
        => Total trapped water = 5 + 5 = 10

For height = 3:
        => leftmost boundary = 0 and rightmost boundary = 4.
        => All blocks in between contain 3 height of water.
        => Earlier we have considered water columns with height 2. So there is increase of 1 unit in height. 
        => So amount of water trapped = (4 – 0 + 1) = 5
        => Total trapped water = 10 + 5 = 15

For height = 4:
        => leftmost boundary = 4 and rightmost boundary = 4.
        => All blocks in between contain 4 height of water. 
        => Earlier we have considered water columns with height 3. So there is increase of 1 unit in height. 
        => So amount of water trapped = (4 – 4 + 1) = 1
        => Total trapped water = 15 + 1 = 16

So total water trapped  = 16 – total space taken by bars = 16 – 9 = 7.

Follow the steps mentioned below to implement the idea:

  • Find the total number of blocks, i.e., the sum of the heights array, num_blocks
  • Find the maximum height, max_height
  • Store total water in a variable, total = 0
  • Keep two pointers, left = 0 and right = N -1, to store the leftmost and the rightmost boundaries for each unit of height
  • For each height, i from 1 to max_height, do the following
    • Find the leftmost and the rightmost boundary for the current height.
    • As mentioned earlier we can consider all the blocks in between these to have at least i unit of water.
    • Add this amount of water to the total trapped water.
  • After the iteration is over, subtract num_blocks from total as we have considered them as water height during calculation.

Below is the implementation of the above approach.

C++




// C++ program to implement the approach
#include <bits/stdc++.h>
using namespace std;
  
int trappedWater(vector<int>& arr)
{
    int num_blocks = 0;
    int n = 0;
    int max_height = INT_MIN;
  
    // Find total blocks, max height and length of array
    for (auto height : arr) {
        num_blocks += height;
        n += 1;
        max_height = max(max_height, height);
    }
  
    // Total water, left pointer and right pointer
    // initialized to 0 and n - 1
    int total = 0;
    int left = 0;
    int right = n - 1;
  
    for (int i = 1; i <= max_height; i++) {
  
        // Find leftmost point greater than current row (i)
        while (arr[left] < i)
            left += 1;
  
        // Find rightmost point greater than current row (i)
        while (arr[right] < i)
            right -= 1;
  
        // water in this row = right - left  + 1
        total += (right - left + 1);
    }
  
    total -= num_blocks;
    return total;
}
  
// Driver code
int main()
{
    vector<int> arr
        = { 0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1 };
  
    // Function call
    cout << trappedWater(arr) << endl;
    return 0;
}
  
// This code is contributed by shinjanpatra


Java




// Java program to determine how much amount of water can an
// elevation map store given in the form of an array of
// height of n points
  
import java.io.*;
  
class GFG {
  
    public static int trappedWater(int arr[])
    {
        // To store the number of blocks
        int n = arr.length;
  
        // To store the sum of all the heights
        int num_blocks = 0;
  
        // To store the maximum height in the array
        int max_height = Integer.MIN_VALUE;
  
        // Compute the sum of all heights and the
        // maximum height given in the array
        for (int i = 0; i < n; i++) {
            max_height = Math.max(max_height, arr[i]);
            num_blocks += arr[i];
        }
  
        // To store the answer and initialise
        // the left and right pointers
        int total = 0, left = 0, right = n - 1;
  
        for (int i = 1; i <= max_height; i++) {
  
            // Compute the leftmost point greater than
            // current row (i)
            while (arr[left] < i) {
                left++;
            }
  
            // Compute the rightmost point greater than
            // current row (i)
            while (arr[right] < i) {
                right--;
            }
  
            // Water in this row = right - left + 1
            total += (right - left + 1);
        }
  
        total -= num_blocks;
        return total;
    }
  
    // Driver Code
    public static void main(String[] args)
    {
        int arr[] = { 0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1 };
  
        // Function call
        System.out.println(trappedWater(arr));
    }
}
  
// this code is contributed by shruti456rawal


Python3




# Python code to implement the approach
  
def trappedWater(arr):
    num_blocks = 0
    n = 0
    max_height = float('-inf')
  
    # Find total blocks, max height and length of array
    for height in arr:
        num_blocks += height
        n += 1
        max_height = max(max_height, height)
  
    # Total water, left pointer and right pointer 
    # initialized to 0 and n - 1
    total = 0
    left = 0
    right = n - 1
  
    for i in range(1, max_height+1):
          
        # Find leftmost point greater than current row (i)
        while arr[left] < i:
            left += 1
          
        # Find rightmost point greater than current row (i)
        while arr[right] < i:
            right -= 1
          
        # Water in this row = right - left + 1
        total += (right - left + 1)
      
    total -= num_blocks
    return total
  
# Driver code
if __name__ == "__main__":
    arr = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]
    print(trappedWater(arr))


Javascript




<script>
  
function trappedWater(arr){
    let num_blocks = 0
    let n = 0
    let max_height =Number.MIN_VALUE
      
    // Find total blocks, max height and length of array    
    for(let height of arr){
        num_blocks += height
        n += 1
        max_height = Math.max(max_height, height)
    }
          
    // Total water, left pointer and right pointer initialized to 0 and n - 1      
    let total = 0
    let left = 0
    let right = n - 1
      
    for(let i = 1;i <= max_height; i++){
        // Find leftmost point greater than current row (i)
        while(arr[left] < i)
            left += 1
          
        // Find rightmost point greater than current row (i)
        while(arr[right] < i)
            right -= 1
          
        // Water in this row = right - left + 1
        total += (right - left + 1)
    }
          
    total -= num_blocks
    return total
}
  
// Driver code
let arr = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]
document.write(trappedWater(arr))
  
// This code is contributed by shinjanpatra
  
</script>


C#




// Include namespace system
using System;
  
  
public class GFG
{
    public static int trappedWater(int[] arr)
    {
        // To store the number of blocks
        var n = arr.Length;
        // To store the sum of all the heights
        var num_blocks = 0;
        // To store the maximum height in the array
        var max_height = int.MinValue;
        // Compute the sum of all heights and the
        // maximum height given in the array
        for (int i = 0; i < n; i++)
        {
            max_height = Math.Max(max_height,arr[i]);
            num_blocks += arr[i];
        }
        // To store the answer and initialise
        // the left and right pointers
        var total = 0;
        var left = 0;
        var right = n - 1;
        for (int i = 1; i <= max_height; i++)
        {
            // Compute the leftmost point greater than
            // current row (i)
            while (arr[left] < i)
            {
                left++;
            }
            // Compute the rightmost point greater than
            // current row (i)
            while (arr[right] < i)
            {
                right--;
            }
            // Water in this row = right - left + 1
            total += (right - left + 1);
        }
        total -= num_blocks;
        return total;
    }
    // Driver Code
    public static void Main(String[] args)
    {
        int[] arr = {0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1};
        // Function call
        Console.WriteLine(GFG.trappedWater(arr));
    }
}


Output

6

Time Complexity: O(max (max_height, N))
Space Complexity: O(1)

Approach 5 (Two Pointer Approach): The idea for this approach is as follows:

At every index, The amount of rainwater stored is the difference between the current index height and a minimum of left max height and right max-height.

Here we can use the two-pointer approach to find the minimum among the left-max and right-max of the probable outermost boundary for any index and iterate likewise.

For example: 

  • Say we have indices i, j and a boundary of (left, right). where i is the left pointer and j is the right pointer.
  • If the minimum is arr[left], we can say that i is bounded in one side by left and no matter whatever the values are in between (i, right), the rightmost boundary of i will at  least have height arr[right] which is the probable outermost boundary for i
  • So the water height of water column at index i is arr[left] – arr[i] and we can increment i then.
  • Similar things happen for j also.

Follow the below illustration for a better understanding:

Illustration:

Consider ar[] = {3, 0, 2, 0, 4}
left = 0, right = 4, l_max = 0, r_max = 0.

left = 0, right = 4:
        => l_max = r_max.
        => water added = 0
        => r_max = 4, l_max = 0
        => right = 3, left = 0

left = 0, right = 3:
        => l_max < r_max.
        => water added = 0
        => r_max = 4, l_max = 3
        => right = 3, left = 1

left = 1, right = 3:
        => l_max < r_max.
        => water added = 3 – 0 = 3
        => r_max = 4, l_max = 3
        => right = 3, left = 2
        => Water trapped = 0 + 3 = 3

left = 2, right = 3:
        => l_max < r_max.
        => water added = 3 – 2 = 1
        => r_max = 4, l_max = 3
        => right = 3, left = 2
        => Water trapped = 3 + 1 = 4

left = 3, right = 3:
        => l_max < r_max.
        => water added = 3 – 0 = 3
        => r_max = 4, l_max = 3
        => right = 3, left = 4
        => Water trapped = 4 + 3 = 7

So total water trapped = 7

Follow the steps mentioned below to implement the idea:

  • Take two pointers l and r. Initialize l to the starting index 0 and r to the last index N-1.
  • Since l is the first element, left_max would be 0, and right_max for r would be 0.
  • While l ? r, iterate the array. We have two possible conditions
  • Condition1 : left_max <= right max
    • Consider Element at index l
    • Since we have traversed all elements to the left of l, left_max is known 
    • For the right max of l, We can say that the right max would  always be >= current r_max here
    • So, min(left_max,right_max) would always equal to left_max in this case
    • Increment l.
  • Condition2 : left_max > right max
    • Consider Element at index r
    • Since we have traversed all elements to the right of r, right_max is known
    • For the left max of l, We can say that the left max would  always be >= current l_max here
    • So, min(left_max,right_max) would always equal to right_max in this case
    • Decrement r.

Below is the implementation of the above approach.

C++




// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
  
int maxWater(int arr[], int n)
    // Indices to traverse the array
    int left = 0;
    int right = n-1;
   
    // To store Left max and right max 
    // for two pointers left and right
    int l_max = 0;
    int r_max = 0;
   
    // To store the total amount 
    // of rain water trapped
    int result = 0;
    while (left <= right)
    {
   
      // We need check for minimum of left 
      // and right max for each element
      if(r_max <= l_max)
      {
   
        // Add the difference between 
        // current value and right max at index r
        result += max(0, r_max-arr[right]);
   
        // Update right max
        r_max = max(r_max, arr[right]);
   
        // Update right pointer
        right -= 1;
      }
      else
      
   
        // Add the difference between 
        // current value and left max at index l
        result += max(0, l_max-arr[left]);
   
        // Update left max
        l_max = max(l_max, arr[left]);
   
        // Update left pointer
        left += 1;
      }
    }
    return result;
}
  
// Driver code
int main() {
    int arr[] = {0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1};
    int N = sizeof(arr)/sizeof(arr[0]);
    cout << maxWater(arr, N) << endl;
    return 0;
}
  
// This code is contributed by avanitrachhadiya2155


Java




// Java implementation of the approach
import java.util.*;
  
class GFG {
  
    static int maxWater(int[] arr, int n)
    {
  
        // Indices to traverse the array
        int left = 0;
        int right = n - 1;
  
        // To store Left max and right max
        // for two pointers left and right
        int l_max = 0;
        int r_max = 0;
  
        // To store the total amount
        // of rain water trapped
        int result = 0;
        while (left <= right) {
  
            // We need check for minimum of left
            // and right max for each element
            if (r_max <= l_max) {
  
                // Add the difference between
                // current value and right max at index r
                result += Math.max(0, r_max - arr[right]);
  
                // Update right max
                r_max = Math.max(r_max, arr[right]);
  
                // Update right pointer
                right -= 1;
            }
            else {
                
                // Add the difference between
                // current value and left max at index l
                result += Math.max(0, l_max - arr[left]);
  
                // Update left max
                l_max = Math.max(l_max, arr[left]);
  
                // Update left pointer
                left += 1;
            }
        }
        return result;
    }
  
    // Driver code
    public static void main(String[] args)
    {
        int[] arr = { 0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1 };
        int N = arr.length;
        System.out.print(maxWater(arr, N));
    }
}
  
// This code is contributed by rutvik_56.


Python3




# Python3 implementation of the approach
  
# Function to return the maximum
# water that can be stored
  
  
def maxWater(arr, n):
      
    # Indices to traverse the array
    left = 0
    right = n-1
  
    # To store Left max and right max 
    # for two pointers left and right
    l_max = 0
    r_max = 0
  
    # To store the total amount 
    # of rain water trapped
    result = 0
    while (left <= right):
          
        # We need check for minimum of left 
        # and right max for each element
        if r_max <= l_max:
              
            # Add the difference between 
            #current value and right max at index r
            result += max(0, r_max-arr[right])
              
            # Update right max
            r_max = max(r_max, arr[right])
              
            # Update right pointer
            right -= 1
        else:
              
            # Add the difference between 
            # current value and left max at index l
            result += max(0, l_max-arr[left])
              
            # Update left max
            l_max = max(l_max, arr[left])
              
            # Update left pointer
            left += 1
    return result
  
  
# Driver code
if __name__ == '__main__':
    arr = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]
    N = len(arr)
    print(maxWater(arr, N))
  
# This code is contributed by Nikhil Chatragadda


C#




// C# implementation of the approach
using System;
class GFG {
  
    static int maxWater(int[] arr, int n)
    {
  
        // indices to traverse the array
        int left = 0;
        int right = n - 1;
  
        // To store Left max and right max
        // for two pointers left and right
        int l_max = 0;
        int r_max = 0;
  
        // To store the total amount
        // of rain water trapped
        int result = 0;
        while (left <= right) {
  
            // We need check for minimum of left
            // and right max for each element
            if (r_max <= l_max) {
  
                // Add the difference between
                // current value and right max at index r
                result += Math.Max(0, r_max - arr[right]);
  
                // Update right max
                r_max = Math.Max(r_max, arr[right]);
  
                // Update right pointer
                right -= 1;
            }
            else {
  
                // Add the difference between
                // current value and left max at index l
                result += Math.Max(0, l_max - arr[left]);
  
                // Update left max
                l_max = Math.Max(l_max, arr[left]);
  
                // Update left pointer
                left += 1;
            }
        }
        return result;
    }
  
    // Driver code
    static void Main()
    {
        int[] arr = { 0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1 };
        int N = arr.Length;
        Console.WriteLine(maxWater(arr, N));
    }
}
  
// This code is contributed by divyeshrabadiya07.


Javascript




<script>
  
// Javascript implementation of the approach
function maxWater(arr, n)
{
      
    // indices to traverse the array
    let left = 0;
    let right = n - 1;
      
    // To store Left max and right max
    // for two pointers left and right
    let l_max = 0;
    let r_max = 0;
      
    // To store the total amount
    // of rain water trapped
    let result = 0;
    while (left <= right)
    {
          
        // We need check for minimum of left
        // and right max for each element
        if(r_max <= l_max)
        {
              
            // Add the difference between
            // current value and right max at index r
            result += Math.max(0, r_max - arr[right]);
              
            // Update right max
            r_max = Math.max(r_max, arr[right]);
              
            // Update right pointer
            right -= 1;
        }
        else
        {
          
            // Add the difference between
            // current value and left max at index l
            result += Math.max(0, l_max - arr[left]);
              
            // Update left max
            l_max = Math.max(l_max, arr[left]);
              
            // Update left pointer
            left += 1;
        }
    }
    return result;
}
  
// Driver code  
let arr = [ 0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1 ];
let N = arr.length;
  
document.write(maxWater(arr, N));
  
// This code is contributed by suresh07
  
</script>


C




// Implementation in C of the above approach
  
// Importing the required header files
#include <stdio.h> // Creating MACRO for finding the maximum number
  
#define max(x, y)(((x) > (y)) ? (x) : (y)) // Creating MACRO for finding the minimum number 
#define min(x, y)(((x) < (y)) ? (x) : (y)) // Function to return the maximum
  
  
int maxWater(int arr[], int n)
{
    
    // indices to traverse the array
    int left = 0;
    int right = n-1;
   
    // To store Left max and right max 
    // for two pointers left and right
    int l_max = 0;
    int r_max = 0;
   
    // To store the total amount 
    // of rain water trapped
    int result = 0;
    while (left <= right)
    {
   
      // We need check for minimum of left 
      // and right max for each element
      if(r_max <= l_max)
      {
   
        // Add the difference between 
        // current value and right max at index r
        result += max(0, r_max-arr[right]);
   
        // Update right max
        r_max = max(r_max, arr[right]);
   
        // Update right pointer
        right -= 1;
      }
      else
      
   
        // Add the difference between 
        // current value and left max at index l
        result += max(0, l_max-arr[left]);
   
        // Update left max
        l_max = max(l_max, arr[left]);
   
        // Update left pointer
        left += 1;
      }
    }
    return result;
}
  
  
// driver code
  
int main() {
    int arr[] = {0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1};
    int N = sizeof(arr) / sizeof(arr[0]);
    printf("%d", maxWater(arr, N));
    return 0;
}


Output

6

Time Complexity: O(N)
Auxiliary Space: O(1) 

Approach 6 (Similar to linear search): Here another efficient solution has been shown.

The concept is that if there is a larger bar to the right, then the water can be retained with a height equal to the smaller bar on the left. 
If there are no larger bars to the right, then start from the right. There must be a larger bar to the left now. 

Follow the steps mentioned below to implement the idea:

  • Loop from index 0 to the end of the given array.
    • If a bar greater than or equal to the previous bar is encountered, then store the index of that bar (say prev_index).
    • Keep adding the previous bar’s height minus the current (ith) bar to the final answer.
    • Have a temporary variable to store the amount of water in the current segment.
    • If no bar greater than or equal to the previous bar is found, then quit.
  • If prev_index < size of the input array, then subtract the temporary variable from the answer, because we have considered the last segment that has no higher right bound.
    • Loop from the end of the input array to prev_index.
    • Find a bar greater than or equal to the previous bar (in this case, the last bar from backward).

Below is the implementation of the above approach.

C++




// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
  
// Function to return the maximum
// water that can be stored
int maxWater(int arr[], int n)
{
    int size = n - 1;
  
    // Let the first element be stored as
    // previous, we shall loop from index 1
    int prev = arr[0];
  
    // To store previous wall's index
    int prev_index = 0;
    int water = 0;
  
    // To store the water until a larger wall
    // is found, if there are no larger walls
    // then delete temp value from water
    int temp = 0;
    for (int i = 1; i <= size; i++) {
  
        // If the current wall is taller than
        // the previous wall then make current
        // wall as the previous wall and its
        // index as previous wall's index
        // for the subsequent loops
        if (arr[i] >= prev) {
            prev = arr[i];
            prev_index = i;
  
            // Because larger or same
            // height wall is found
            temp = 0;
        }
        else {
  
            // Since current wall is shorter than
            // the previous, we subtract previous
            // wall's height from the current wall's
            // height and add it to the water
            water += prev - arr[i];
  
            // Store the same value in temp as well
            // If we dont find any larger wall then
            // we will subtract temp from water
            temp += prev - arr[i];
        }
    }
  
    // If the last wall was larger than or equal
    // to the previous wall then prev_index would
    // be equal to size of the array (last element)
    // If we didn't find a wall greater than or equal
    // to the previous wall from the left then
    // prev_index must be less than the index
    // of the last element
    if (prev_index < size) {
  
        // Temp would've stored the water collected
        // from previous largest wall till the end
        // of array if no larger wall was found then
        // it has excess water and remove that
        // from water variable
        water -= temp;
  
        // We start from the end of the array,
        // so previous should be assigned to
        // the last element
        prev = arr[size];
  
        // Loop from the end of array up to the
        // previous index which would contain
        // the largest wall from the left
        for (int i = size; i >= prev_index; i--) {
  
            // Right end wall will be definitely
            // smaller than the 'previous index' wall
            if (arr[i] >= prev) {
                prev = arr[i];
            }
            else {
                water += prev - arr[i];
            }
        }
    }
  
    // Return the maximum water
    return water;
}
  
// Driver Code
int main()
{
    int arr[] = { 0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1 };
    int N = sizeof(arr) / sizeof(arr[0]);
  
    cout << maxWater(arr, N);
    return 0;
}
  
// This code is contributed by Debidutta Rath


Java




// Java implementation of the approach
class GFG {
  
    // Function to return the maximum
    // water that can be stored
    public static int maxWater(int arr[], int n)
    {
        int size = n - 1;
  
        // Let the first element be stored as
        // previous, we shall loop from index 1
        int prev = arr[0];
  
        // To store previous wall's index
        int prev_index = 0;
        int water = 0;
  
        // To store the water until a larger wall
        // is found, if there are no larger walls
        // then delete temp value from water
        int temp = 0;
        for (int i = 1; i <= size; i++) {
  
            // If the current wall is taller than
            // the previous wall then make current
            // wall as the previous wall and its
            // index as previous wall's index
            // for the subsequent loops
            if (arr[i] >= prev) {
                prev = arr[i];
                prev_index = i;
  
                // Because larger or same height wall is
                // found
                temp = 0;
            }
            else {
  
                // Since current wall is shorter than
                // the previous, we subtract previous
                // wall's height from the current wall's
                // height and add it to the water
                water += prev - arr[i];
  
                // Store the same value in temp as well
                // If we dont find any larger wall then
                // we will subtract temp from water
                temp += prev - arr[i];
            }
        }
  
        // If the last wall was larger than or equal
        // to the previous wall then prev_index would
        // be equal to size of the array (last element)
        // If we didn't find a wall greater than or equal
        // to the previous wall from the left then
        // prev_index must be less than the index
        // of the last element
        if (prev_index < size) {
  
            // Temp would've stored the water collected
            // from previous largest wall till the end
            // of array if no larger wall was found then
            // it has excess water and remove that
            // from 'water' var
            water -= temp;
  
            // We start from the end of the array, so
            // previous should be assigned to the last
            // element
            prev = arr[size];
  
            // Loop from the end of array up to the
            // 'previous index' which would contain the
            // "largest wall from the left"
            for (int i = size; i >= prev_index; i--) {
  
                // Right end wall will be definitely smaller
                // than the 'previous index' wall
                if (arr[i] >= prev) {
                    prev = arr[i];
                }
                else {
                    water += prev - arr[i];
                }
            }
        }
  
        // Return the maximum water
        return water;
    }
  
    // Driver code
    public static void main(String[] args)
    {
        int arr[] = { 0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1 };
        int N = arr.length;
        System.out.print(maxWater(arr, N));
    }
}


Python3




# Python3 implementation of the approach
  
# Function to return the maximum
# water that can be stored
  
  
def maxWater(arr, n):
    size = n - 1
  
    # Let the first element be stored as
    # previous, we shall loop from index 1
    prev = arr[0]
  
    # To store previous wall's index
    prev_index = 0
    water = 0
  
    # To store the water until a larger wall
    # is found, if there are no larger walls
    # then delete temp value from water
    temp = 0
    for i in range(1, size + 1):
  
        # If the current wall is taller than
        # the previous wall then make current
        # wall as the previous wall and its
        # index as previous wall's index
        # for the subsequent loops
        if (arr[i] >= prev):
            prev = arr[i]
            prev_index = i
  
            # Because larger or same height wall is found
            temp = 0
        else:
  
            # Since current wall is shorter than
            # the previous, we subtract previous
            # wall's height from the current wall's
            # height and add it to the water
            water += prev - arr[i]
  
            # Store the same value in temp as well
            # If we dont find any larger wall then
            # we will subtract temp from water
            temp += prev - arr[i]
  
    # If the last wall was larger than or equal
    # to the previous wall then prev_index would
    # be equal to size of the array (last element)
    # If we didn't find a wall greater than or equal
    # to the previous wall from the left then
    # prev_index must be less than the index
    # of the last element
    if (prev_index < size):
  
        # Temp would've stored the water collected
        # from previous largest wall till the end
        # of array if no larger wall was found then
        # it has excess water and remove that
        # from 'water' var
        water -= temp
  
        # We start from the end of the array, so previous
        # should be assigned to the last element
        prev = arr[size]
  
        # Loop from the end of array up to the 'previous index'
        # which would contain the "largest wall from the left"
        for i in range(size, prev_index - 1, -1):
  
            # Right end wall will be definitely smaller
            # than the 'previous index' wall
            if (arr[i] >= prev):
                prev = arr[i]
            else:
                water += prev - arr[i]
  
    # Return the maximum water
    return water
  
  
# Driver code
if __name__ == '__main__':
    arr = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]
    N = len(arr)
    print(maxWater(arr, N))
  
# This code is contributed by Mohit Kumar


C#




// C# implementation of the approach
using System;
class GFG {
  
    // Function to return the maximum
    // water that can be stored
    static int maxWater(int[] arr, int n)
    {
        int size = n - 1;
  
        // Let the first element be stored as
        // previous, we shall loop from index 1
        int prev = arr[0];
  
        // To store previous wall's index
        int prev_index = 0;
        int water = 0;
  
        // To store the water until a larger wall
        // is found, if there are no larger walls
        // then delete temp value from water
        int temp = 0;
        for (int i = 1; i <= size; i++) {
  
            // If the current wall is taller than
            // the previous wall then make current
            // wall as the previous wall and its
            // index as previous wall's index
            // for the subsequent loops
            if (arr[i] >= prev) {
                prev = arr[i];
                prev_index = i;
  
                // Because larger or same
                // height wall is found
                temp = 0;
            }
            else {
  
                // Since current wall is shorter than
                // the previous, we subtract previous
                // wall's height from the current wall's
                // height and add it to the water
                water += prev - arr[i];
  
                // Store the same value in temp as well
                // If we dont find any larger wall then
                // we will subtract temp from water
                temp += prev - arr[i];
            }
        }
  
        // If the last wall was larger than or equal
        // to the previous wall then prev_index would
        // be equal to size of the array (last element)
        // If we didn't find a wall greater than or equal
        // to the previous wall from the left then
        // prev_index must be less than the index
        // of the last element
        if (prev_index < size) {
  
            // Temp would've stored the water collected
            // from previous largest wall till the end
            // of array if no larger wall was found then
            // it has excess water and remove that
            // from water variable
            water -= temp;
  
            // We start from the end of the array,
            // so previous should be assigned to
            // the last element
            prev = arr[size];
  
            // Loop from the end of array up to the
            // previous index which would contain
            // the largest wall from the left
            for (int i = size; i >= prev_index; i--) {
  
                // Right end wall will be definitely
                // smaller than the 'previous index' wall
                if (arr[i] >= prev) {
                    prev = arr[i];
                }
                else {
                    water += prev - arr[i];
                }
            }
        }
  
        // Return the maximum water
        return water;
    }
  
    // Driver code
    static void Main()
    {
        int[] arr = { 0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1 };
        int N = arr.Length;
        Console.WriteLine(maxWater(arr, N));
    }
}
  
// This code is contributed by divyesh072019


Javascript




<script>
  
// JavaScript implementation of the approach
  
    // Function to return the maximum
    // water that can be stored
    function maxWater(arr,n)
    {
        let size = n - 1;
   
        // Let the first element be stored as
        // previous, we shall loop from index 1
        let prev = arr[0];
   
        // To store previous wall's index
        let prev_index = 0;
        let water = 0;
   
        // To store the water until a larger wall
        // is found, if there are no larger walls
        // then delete temp value from water
        let temp = 0;
        for (let i = 1; i <= size; i++) {
   
            // If the current wall is taller than
            // the previous wall then make current
            // wall as the previous wall and its
            // index as previous wall's index
            // for the subsequent loops
            if (arr[i] >= prev) {
                prev = arr[i];
                prev_index = i;
   
                // Because larger or same height wall is found
                temp = 0;
            }
            else {
   
                // Since current wall is shorter than
                // the previous, we subtract previous
                // wall's height from the current wall's
                // height and add it to the water
                water += prev - arr[i];
   
                // Store the same value in temp as well
                // If we dont find any larger wall then
                // we will subtract temp from water
                temp += prev - arr[i];
            }
        }
   
        // If the last wall was larger than or equal
        // to the previous wall then prev_index would
        // be equal to size of the array (last element)
        // If we didn't find a wall greater than or equal
        // to the previous wall from the left then
        // prev_index must be less than the index
        // of the last element
        if (prev_index < size) {
   
            // Temp would've stored the water collected
            // from previous largest wall till the end
            // of array if no larger wall was found then
            // it has excess water and remove that
            // from 'water' var
            water -= temp;
   
            // We start from the end of the array, so previous
            // should be assigned to the last element
            prev = arr[size];
   
            // Loop from the end of array up to the 'previous index'
            // which would contain the "largest wall from the left"
            for (let i = size; i >= prev_index; i--) {
   
                // Right end wall will be definitely smaller
                // than the 'previous index' wall
                if (arr[i] >= prev) {
                    prev = arr[i];
                }
                else {
                    water += prev - arr[i];
                }
            }
        }
   
        // Return the maximum water
        return water;
    }
      
    // Driver code
    let arr=[ 0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1];
    let N = arr.length;
    document.write(maxWater(arr, N));
  
  
// This code is contributed by patel2127
  
</script>


C




// Implementation in C of the above approach
  
// Importing the required header files
#include <stdio.h> // Creating MACRO for finding the maximum number
  
#define max(x, y)                                          \
    (((x) > (y)) ? (x) : (y)) // Creating MACRO for finding
                              // the minimum number
#define min(x, y)                                          \
    (((x) < (y)) ? (x)                                     \
                 : (y)) // Function to return the maximum
  
// water that can be stored
int maxWater(int arr[], int n)
{
  
    int size = n - 1;
  
    // Let the first element be stored as
    // previous, we shall loop from index 1
    int prev = arr[0];
  
    // To store previous wall's index
    int prev_index = 0;
    int water = 0;
  
    // To store the water until a larger wall
    // is found, if there are no larger walls
    // then delete temp value from water
    int temp = 0;
  
    for (int i = 1; i <= size; i++) {
  
        // If the current wall is taller than
        // the previous wall then make current
        // wall as the previous wall and its
        // index as previous wall's index
        // for the subsequent loops
        if (arr[i] >= prev) {
            prev = arr[i];
            prev_index = i;
  
            // Because larger or same
            // height wall is found
            temp = 0;
        }
        else {
  
            // Since current wall is shorter than
            // the previous, we subtract previous
            // wall's height from the current wall's
            // height and add it to the water
            water += prev - arr[i];
  
            // Store the same value in temp as well
            // If we dont find any larger wall then
            // we will subtract temp from water
            temp += prev - arr[i];
        }
    }
  
    // If the last wall was larger than or equal
    // to the previous wall then prev_index would
    // be equal to size of the array (last element)
    // If we didn't find a wall greater than or equal
    // to the previous wall from the left then
    // prev_index must be less than the index
    // of the last element
    if (prev_index < size) {
  
        // Temp would've stored the water collected
        // from previous largest wall till the end
        // of array if no larger wall was found then
        // it has excess water and remove that
        // from water variable
        water -= temp;
  
        // We start from the end of the array,
        // so previous should be assigned to
        // the last element
        prev = arr[size];
  
        // Loop from the end of array up to the
        // previous index which would contain
        // the largest wall from the left
        for (int i = size; i >= prev_index; i--) {
  
            // Right end wall will be definitely
            // smaller than the 'previous index' wall
            if (arr[i] >= prev) {
                prev = arr[i];
            }
            else {
                water += prev - arr[i];
            }
        }
    }
  
    // Return the maximum water
    return water;
}
  
// driver code
  
int main()
{
    int arr[] = { 0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1 };
    int N = sizeof(arr) / sizeof(arr[0]);
    printf("%d", maxWater(arr, N));
    return 0;
}


Output

6

Time Complexity: O(N)
Auxiliary Space: O(1). 

 



Last Updated : 20 Feb, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads