Maximum water that can be stored between two buildings - GeeksforGeeks

11 Feb, 2022
Given an integer array which represents the heights of N buildings, the task is to delete N-2 buildings such that the water that can be trapped between the remaining two building is maximum. Please note that the total water trapped between two buildings is gap between them (number of buildings removed) multiplied by height of the smaller building.
Examples: 
Input: arr[] = {1, 3, 4} Output: 1 We have to calculate the maximum water that can be stored between any 2 buildings. Water between the buildings of height 1 and height 3 = 0. Water between the buildings of height 1 and height 4 = 1. Water between the buildings of height 3 and height 4 = 0. Hence maximum of all the cases is 1.
Input: arr[] = {2, 1, 3, 4, 6, 5} Output: 8 We remove the middle 4 buildings and get the total water stored as 2 * 4 = 8  
Naive approach: Check for all possible pairs and the pair which can hold maximum water will be the answer. Water stored between two buildings of height h1 and h2 would be equal to: 
minimum(h1, h2)*(distance between the buildings-1)
Our task is to maximize this value for every pair.
Below is the implementation of the above approach: 
C++
Java
Python3
C#
Javascript
// C++ implementation of the above approach#include <bits/stdc++.h>using namespace std; // Return the maximum water that can be storedint maxWater(int height[], int n){    int maximum = 0;     // Check all possible pairs of buildings    for (int i = 0; i < n - 1; i++) {        for (int j = i + 1; j < n; j++) {            int current = (min(height[i],                               height[j])                           * (j - i - 1));             // Maximum so far            maximum = max(maximum, current);        }    }    return maximum;} // Driver codeint main(){    int height[] = { 2, 1, 3, 4, 6, 5 };    int n = sizeof(height) / sizeof(height[0]);    cout << maxWater(height, n);    return 0;} // This code is contributed by ihritik
// Java implementation of the above approachclass GFG {     // Return the maximum water that can be stored    static int maxWater(int height[], int n)    {        int max = 0;         // Check all possible pairs of buildings        for (int i = 0; i < n - 1; i++) {            for (int j = i + 1; j < n; j++) {                int current = (Math.min(height[i],                                        height[j])                               * (j - i - 1));                 // Maximum so far                max = Math.max(max, current);            }        }        return max;    }     // Driver code    public static void main(String[] args)    {        int height[] = { 2, 1, 3, 4, 6, 5 };        int n = height.length;        System.out.print(maxWater(height, n));    }}
# Python3 implementation of the above approach # Return the maximum water# that can be storeddef maxWater(height, n) :    maximum = 0;     # Check all possible pairs of buildings    for i in range(n - 1) :        for j in range(i + 1, n) :            current = min(height[i],                          height[j]) * (j - i - 1);             # Maximum so far            maximum = max(maximum, current);                 return maximum;     # Driver codeif __name__ == "__main__" :    height = [ 2, 1, 3, 4, 6, 5 ];         n = len(height);    print(maxWater(height, n)); # This code is contributed by AnkitRai01
// C# implementation of the above approachusing System; class GFG {     // Return the maximum water that can be stored    static int maxWater(int[] height, int n)    {        int max = 0;         // Check all possible pairs of buildings        for (int i = 0; i < n - 1; i++) {            for (int j = i + 1; j < n; j++) {                int current = (Math.Min(height[i],                                        height[j])                               * (j - i - 1));                 // Maximum so far                max = Math.Max(max, current);            }        }        return max;    }     // Driver code    static public void Main()    {        int[] height = { 2, 1, 3, 4, 6, 5 };        int n = height.Length;        Console.WriteLine(maxWater(height, n));    }} // This code is contributed by @tushil.
<script> // Javascript implementation of the above approach // Return the maximum water that can be storedfunction maxWater( height, n){    let maximum = 0;     // Check all possible pairs of buildings    for (let i = 0; i < n - 1; i++) {        for (let j = i + 1; j < n; j++) {            let current = (Math.min(height[i],                               height[j])                           * (j - i - 1));             // Maximum so far            maximum = Math.max(maximum, current);        }    }    return maximum;}          // Driver program         let height = [ 2, 1, 3, 4, 6, 5 ];    let n = height.length;    document.write(maxWater(height, n));          </script>
8
 
Time Complexity: O(N*N)
Efficient approach: 
Sort the array according to increasing height without affecting the original indices i.e. make pairs of (element, index).
Then for every element, assume it is the building with the minimum height among the two buildings required then the height of the required water will be equal to the height of the chosen building and the width will be equal to the index difference between the chosen building and the building to be found.
In order to choose the other building which maximizes the water, the other building has to be as far as possible and must be greater in height as compared to the currently chosen building.
Now, the problem gets reduced to finding the minimum and maximum indices on the right for every building in the sorted array.
Below is the implementation of the above approach:  
C++
Java
// C++ implementation of the above approach#include<bits/stdc++.h>using namespace std; bool compareTo(pair<int, int> p1,               pair<int, int> p2){    return p1.second < p2.second;} // Return the maximum water that// can be storedint maxWater(int height[], int n){         // Make pairs with indices    pair<int, int> pairs[n];    for(int i = 0; i < n; i++)        pairs[i] = make_pair(i, height[i]);             // Sort array based on heights    sort(pairs, pairs + n, compareTo);                // To store the min and max index so far    // from the right    int minIndSoFar = pairs[n - 1].first;    int maxIndSoFar = pairs[n - 1].first;    int maxi = 0;         for(int i = n - 2; i >= 0; i--)    {                 // Current building paired with        // the building greater in height        // and on the extreme left        int left = 0;        if (minIndSoFar < pairs[i].first)        {            left = (pairs[i].second *                   (pairs[i].first -                        minIndSoFar - 1));        }         // Current building paired with        // the building greater in height        // and on the extreme right        int right = 0;        if (maxIndSoFar > pairs[i].first)        {            right = (pairs[i].second *                        (maxIndSoFar -                      pairs[i].first - 1));        }         // Maximum so far        maxi = max(left, max(right, maxi));         // Update the maximum and minimum so far        minIndSoFar = min(minIndSoFar,                          pairs[i].first);        maxIndSoFar = max(maxIndSoFar,                          pairs[i].first);    }    return maxi;} // Driver codeint main( ){    int height[] = { 2, 1, 3, 4, 6, 5 };    int n = sizeof(height) / sizeof(height[0]);         cout << maxWater(height, n);} // This code is contributed by manupathria
// Java implementation of the above approachimport java.util.Arrays; // Class to store the pairsclass Pair implements Comparable<Pair> {    int ind, val;     Pair(int ind, int val)    {        this.ind = ind;        this.val = val;    }     @Override    public int compareTo(Pair o)    {        if (this.val > o.val)            return 1;        return -1;    }} class GFG {     // Return the maximum water that can be stored    static int maxWater(int height[], int n)    {         // Make pairs with indices        Pair pairs[] = new Pair[n];        for (int i = 0; i < n; i++)            pairs[i] = new Pair(i, height[i]);         // Sort array based on heights        Arrays.sort(pairs);         // To store the min and max index so far        // from the right        int minIndSoFar = pairs[n - 1].ind;        int maxIndSoFar = pairs[n - 1].ind;        int max = 0;        for (int i = n - 2; i >= 0; i--) {             // Current building paired with the building            // greater in height and on the extreme left            int left = 0;            if (minIndSoFar < pairs[i].ind) {                left = (pairs[i].val * (pairs[i].ind - minIndSoFar - 1));            }             // Current building paired with the building            // greater in height and on the extreme right            int right = 0;            if (maxIndSoFar > pairs[i].ind) {                right = (pairs[i].val * (maxIndSoFar - pairs[i].ind - 1));            }             // Maximum so far            max = Math.max(left, Math.max(right, max));             // Update the maximum and minimum so far            minIndSoFar = Math.min(minIndSoFar,                                   pairs[i].ind);            maxIndSoFar = Math.max(maxIndSoFar,                                   pairs[i].ind);        }         return max;    }     // Driver code    public static void main(String[] args)    {        int height[] = { 2, 1, 3, 4, 6, 5 };        int n = height.length;         System.out.print(maxWater(height, n));    }}
8
 
Time Complexity : O(N*log(N))
Two pointer approach: Take two pointers i and j pointing to the first and the last building respectively and calculate the water that can be stored between these two buildings. Now increment i if height[i] < height[j] else decrement j. This is because the water that can be trapped is dependent on the height of the small building and moving from the greater height building will just reduce the amount of water instead of maximizing it. In the end, print the maximum amount of water calculated so far.
Below is the implementation of the above approach:  
C++
Java
Python3
C#
Javascript
// C++ implementation of the approach#include<bits/stdc++.h>using namespace std; // Return the maximum water that can be storedint maxWater(int height[], int n){     // To store the maximum water so far    int maximum = 0;     // Both the pointers are pointing at the first    // and the last buildings respectively    int i = 0, j = n - 1;     // While the water can be stored between    // the currently chosen buildings    while (i < j)    {         // Update maximum water so far and increment i        if (height[i] < height[j])        {            maximum = max(maximum, (j - i - 1) * height[i]);            i++;        }         // Update maximum water so far and decrement j        else if (height[j] < height[i])        {            maximum = max(maximum, (j - i - 1) * height[j]);            j--;        }         // Any of the pointers can be updated (or both)        else        {            maximum = max(maximum, (j - i - 1) * height[i]);            i++;            j--;        }    }     return maximum;}  // Driver codeint main(){     int height[] = { 2, 1, 3, 4, 6, 5 };     int n = sizeof(height)/sizeof(height[0]);     cout<<(maxWater(height, n));} // This code is contributed by CrazyPro
// Java implementation of the approachimport java.util.Arrays; class GFG {     // Return the maximum water that can be stored    static int maxWater(int height[], int n)    {         // To store the maximum water so far        int max = 0;         // Both the pointers are pointing at the first        // and the last buildings respectively        int i = 0, j = n - 1;         // While the water can be stored between        // the currently chosen buildings        while (i < j) {             // Update maximum water so far and increment i            if (height[i] < height[j]) {                max = Math.max(max, (j - i - 1) * height[i]);                i++;            }             // Update maximum water so far and decrement j            else if (height[j] < height[i]) {                max = Math.max(max, (j - i - 1) * height[j]);                j--;            }             // Any of the pointers can be updated (or both)            else {                max = Math.max(max, (j - i - 1) * height[i]);                i++;                j--;            }        }         return max;    }     // Driver code    public static void main(String[] args)    {        int height[] = { 2, 1, 3, 4, 6, 5 };        int n = height.length;         System.out.print(maxWater(height, n));    }}
# Python3 implementation of the approach # Return the maximum water that can be storeddef maxWater(height, n):     # To store the maximum water so far    maximum = 0;     # Both the pointers are pointing at the first    # and the last buildings respectively    i = 0    j = n - 1     # While the water can be stored between    # the currently chosen buildings    while (i < j):             # Update maximum water so far and increment i        if (height[i] < height[j]):                maximum = max(maximum, (j - i - 1) * height[i]);            i += 1;                 # Update maximum water so far and decrement j        elif (height[j] < height[i]):            maximum = max(maximum, (j - i - 1) * height[j]);            j -= 1;                 # Any of the pointers can be updated (or both)        else:                maximum = max(maximum, (j - i - 1) * height[i]);            i += 1;            j -= 1;             return maximum; # Driver codeheight = [2, 1, 3, 4, 6, 5] n = len(height) print (maxWater(height, n)); # This code is contributed by CrazyPro
// C# implementation of the approachusing System; class GFG{         // Return the maximum water that can be stored    static int maxWater(int []height, int n)    {         // To store the maximum water so far        int max = 0;         // Both the pointers are pointing at the first        // and the last buildings respectively        int i = 0, j = n - 1;         // While the water can be stored between        // the currently chosen buildings        while (i < j)        {             // Update maximum water so far and increment i            if (height[i] < height[j])            {                max = Math.Max(max, (j - i - 1) * height[i]);                i++;            }             // Update maximum water so far and decrement j            else if (height[j] < height[i])            {                max = Math.Max(max, (j - i - 1) * height[j]);                j--;            }             // Any of the pointers can be updated (or both)            else            {                max = Math.Max(max, (j - i - 1) * height[i]);                i++;                j--;            }        }         return max;    }     // Driver code    static public void Main ()    {                 int []height = { 2, 1, 3, 4, 6, 5 };        int n = height.Length;         Console.Write(maxWater(height, n));    }} // This code is contributed by jit_t
<script> // Javascript implementation of the approach // Return the maximum water that can be storedfunction maxWater(height, n){     // To store the maximum water so far    var maximum = 0;     // Both the pointers are pointing at the first    // and the last buildings respectively    var i = 0, j = n - 1;     // While the water can be stored between    // the currently chosen buildings    while (i < j)    {         // Update maximum water so far and increment i        if (height[i] < height[j])        {            maximum = Math.max(maximum, (j - i - 1) * height[i]);            i++;        }         // Update maximum water so far and decrement j        else if (height[j] < height[i])        {            maximum = Math.max(maximum, (j - i - 1) * height[j]);            j--;        }         // Any of the pointers can be updated (or both)        else        {            maximum = Math.max(maximum, (j - i - 1) * height[i]);            i++;            j--;        }    }     return maximum;}  // Driver codevar height = [ 2, 1, 3, 4, 6, 5 ];var n = height.length;document.write(maxWater(height, n))   </script>
8
 
Time Complexity: O(N)
jit_t
ankthon
ihritik
gp6
CrazyPro
manupathria
saisatwik2226
jana_sayantan
rutvik_56
simmytarika5
Constructive Algorithms
Arrays
Sorting
Arrays
Sorting
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
Program to find sum of elements in a given array
Building Heap from Array
Window Sliding Technique
1's and 2's complement of a Binary Number
Reversal algorithm for array rotation