Given an integer array that 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 buildings is maximum. The total water trapped between two buildings is a gap between them (the number of buildings removed) multiplied by the height of the smaller building.
Examples:
Input: arr[] = {1, 3, 4}
Output: 1
Explanation: 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 heights h1 and h2 would be equal to minimum(h1, h2)*(distance between the buildings – 1), maximize this value to get the answer.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int maxWater( int height[], int n)
{
int maximum = 0;
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 = max(maximum, current);
}
}
return maximum;
}
int main()
{
int height[] = { 2, 1, 3, 4, 6, 5 };
int n = sizeof (height) / sizeof (height[0]);
cout << maxWater(height, n);
return 0;
}
|
Java
class GFG {
static int maxWater( int height[], int n)
{
int max = 0 ;
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 ));
max = Math.max(max, current);
}
}
return max;
}
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
def maxWater(height, n):
maximum = 0
for i in range (n - 1 ):
for j in range (i + 1 , n):
current = min (height[i],
height[j]) * (j - i - 1 )
maximum = max (maximum, current)
return maximum
if __name__ = = "__main__" :
height = [ 2 , 1 , 3 , 4 , 6 , 5 ]
n = len (height)
print (maxWater(height, n))
|
C#
using System;
class GFG {
static int maxWater( int [] height, int n)
{
int max = 0;
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));
max = Math.Max(max, current);
}
}
return max;
}
static public void Main()
{
int [] height = { 2, 1, 3, 4, 6, 5 };
int n = height.Length;
Console.WriteLine(maxWater(height, n));
}
}
|
Javascript
<script>
function maxWater( height, n)
{
let maximum = 0;
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 = Math.max(maximum, current);
}
}
return maximum;
}
let height = [ 2, 1, 3, 4, 6, 5 ];
let n = height.length;
document.write(maxWater(height, n));
</script>
|
Time Complexity: O(N*N)
Auxiliary Space: O(1)
Maximum water that can be stored between two buildings using sorting
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.
Follow the steps below to implement the idea:
- Create an array of pairs pairs[] of size N with each pair of the type (i, arr[i]) and sort pairs[] in increasing order of second element of pair.
- Initialize minIndSoFar = pairs[n – 1].first and maxIndSoFar = pairs[n – 1].first as this would be the index of largest buildings on either sides of i and a variable maxi that will store the value of maximum water that can be stored.
- Run a for loop with counter i from N – 2 to 0
- Calculate the water that can be filled between the building on index i and minIndSoFar as ith building will be of same of less height than the building on minIndSoFar, so left = (pairs[i].second * (pairs[i].first – minIndSoFar – 1)).
- Calculate the water that can be filled between the building on index i and maxIndSoFar as ith building will be of same of less height than the building on maxIndSoFar, so right = (pairs[i].second *(maxIndSoFar – pairs[i].first – 1)).
- Now maximize maxi with max of left, right and maxi, update maxIndSoFar with max of maxIndSoFar and i, and minIndSoFar with min of maxIndSoFar and i.
- Return maxi.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
bool compareTo(pair< int , int > p1, pair< int , int > p2)
{
return p1.second < p2.second;
}
int maxWater( int height[], int n)
{
pair< int , int > pairs[n];
for ( int i = 0; i < n; i++)
pairs[i] = make_pair(i, height[i]);
sort(pairs, pairs + n, compareTo);
int minIndSoFar = pairs[n - 1].first;
int maxIndSoFar = pairs[n - 1].first;
int maxi = 0;
for ( int i = n - 2; i >= 0; i--) {
int left = 0;
if (minIndSoFar < pairs[i].first) {
left = (pairs[i].second
* (pairs[i].first - minIndSoFar - 1));
}
int right = 0;
if (maxIndSoFar > pairs[i].first) {
right = (pairs[i].second
* (maxIndSoFar - pairs[i].first - 1));
}
maxi = max(left, max(right, maxi));
minIndSoFar = min(minIndSoFar, pairs[i].first);
maxIndSoFar = max(maxIndSoFar, pairs[i].first);
}
return maxi;
}
int main()
{
int height[] = { 2, 1, 3, 4, 6, 5 };
int n = sizeof (height) / sizeof (height[0]);
cout << maxWater(height, n);
}
|
Java
import java.util.Arrays;
class 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 {
static int maxWater( int height[], int n)
{
Pair pairs[] = new Pair[n];
for ( int i = 0 ; i < n; i++)
pairs[i] = new Pair(i, height[i]);
Arrays.sort(pairs);
int minIndSoFar = pairs[n - 1 ].ind;
int maxIndSoFar = pairs[n - 1 ].ind;
int max = 0 ;
for ( int i = n - 2 ; i >= 0 ; i--) {
int left = 0 ;
if (minIndSoFar < pairs[i].ind) {
left = (pairs[i].val
* (pairs[i].ind - minIndSoFar - 1 ));
}
int right = 0 ;
if (maxIndSoFar > pairs[i].ind) {
right
= (pairs[i].val
* (maxIndSoFar - pairs[i].ind - 1 ));
}
max = Math.max(left, Math.max(right, max));
minIndSoFar
= Math.min(minIndSoFar, pairs[i].ind);
maxIndSoFar
= Math.max(maxIndSoFar, pairs[i].ind);
}
return max;
}
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
from functools import cmp_to_key
def compareTo(p1, p2):
return p1[ 1 ] - p2[ 1 ]
def maxWater(height, n):
pairs = [ 0 for i in range (n)]
for i in range (n):
pairs[i] = [i, height[i]]
pairs.sort(key = cmp_to_key(compareTo))
minIndSoFar = pairs[n - 1 ][ 0 ]
maxIndSoFar = pairs[n - 1 ][ 0 ]
maxi = 0
for i in range (n - 2 , - 1 , - 1 ):
left = 0
if (minIndSoFar < pairs[i][ 0 ]):
left = (pairs[i][ 1 ] *
(pairs[i][ 0 ] -
minIndSoFar - 1 ))
right = 0
if (maxIndSoFar > pairs[i][ 0 ]):
right = (pairs[i][ 1 ] *
(maxIndSoFar -
pairs[i][ 0 ] - 1 ))
maxi = max (left, max (right, maxi))
minIndSoFar = min (minIndSoFar,
pairs[i][ 0 ])
maxIndSoFar = max (maxIndSoFar,
pairs[i][ 0 ])
return maxi
height = [ 2 , 1 , 3 , 4 , 6 , 5 ]
n = len (height)
print (maxWater(height, n))
|
C#
using System;
using System.Linq;
class Program
{
static int CompareTo(Tuple< int , int > p1, Tuple< int , int > p2)
{
return p1.Item2.CompareTo(p2.Item2);
}
static int MaxWater( int [] height, int n)
{
Tuple< int , int >[] pairs = new Tuple< int , int >[n];
for ( int i = 0; i < n; i++)
pairs[i] = Tuple.Create(i, height[i]);
Array.Sort(pairs, CompareTo);
int minIndSoFar = pairs[n - 1].Item1;
int maxIndSoFar = pairs[n - 1].Item1;
int maxi = 0;
for ( int i = n - 2; i >= 0; i--)
{
int left = 0;
if (minIndSoFar < pairs[i].Item1)
{
left = (pairs[i].Item2 * (pairs[i].Item1 - minIndSoFar - 1));
}
int right = 0;
if (maxIndSoFar > pairs[i].Item1)
{
right = (pairs[i].Item2 * (maxIndSoFar - pairs[i].Item1 - 1));
}
maxi = Math.Max(left, Math.Max(right, maxi));
minIndSoFar = Math.Min(minIndSoFar, pairs[i].Item1);
maxIndSoFar = Math.Max(maxIndSoFar, pairs[i].Item1);
}
return maxi;
}
static void Main( string [] args)
{
int [] height = { 2, 1, 3, 4, 6, 5 };
int n = height.Length;
Console.WriteLine(MaxWater(height, n));
}
}
|
Javascript
<script>
function compareTo(p1,p2)
{
return p1[1] - p2[1];
}
function maxWater(height, n)
{
let pairs = new Array(n);
for (let i = 0; i < n; i++)
pairs[i] = [i, height[i]];
pairs.sort(compareTo);
let minIndSoFar = pairs[n - 1][0];
let maxIndSoFar = pairs[n - 1][0];
let maxi = 0;
for (let i = n - 2; i >= 0; i--)
{
let left = 0;
if (minIndSoFar < pairs[i][0])
{
left = (pairs[i][1] *
(pairs[i][0] -
minIndSoFar - 1));
}
let right = 0;
if (maxIndSoFar > pairs[i][0])
{
right = (pairs[i][1] *
(maxIndSoFar -
pairs[i][0] - 1));
}
maxi = Math.max(left, Math.max(right, maxi));
minIndSoFar = Math.min(minIndSoFar,
pairs[i][0]);
maxIndSoFar = Math.max(maxIndSoFar,
pairs[i][0]);
}
return maxi;
}
let height = [ 2, 1, 3, 4, 6, 5 ];
let n = height.length;
document.write(maxWater(height, n), "</br>" );
</script>
|
Time Complexity : O(N*log(N))
Auxiliary Space: O(N)
Maximum water that can be stored between two buildings using Two pointer approach:
Below is the idea to solve the problem
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.
Follow the below steps to implement the idea:
- Initialize variable maximum to store maximum water that can be stored, i and j pointing to the first and the last.
- Run a while loop till i < j
- If height[i] < height[j] update maximum = max(maximum, (j – i – 1) * height[i]) and increment i by 1.
- Else maximum will be updated according to right height i.e. building at j maximum = max(maximum, (j – i – 1) * height[j]) and decrement j by 1.
- return maximum.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int maxWater( int height[], int n)
{
int maximum = 0;
int i = 0, j = n - 1;
while (i < j) {
if (height[i] < height[j]) {
maximum = max(maximum, (j - i - 1) * height[i]);
i++;
}
else {
maximum = max(maximum, (j - i - 1) * height[j]);
j--;
}
}
return maximum;
}
int main()
{
int height[] = { 2, 1, 3, 4, 6, 5 };
int n = sizeof (height) / sizeof (height[0]);
cout << (maxWater(height, n));
}
|
Java
import java.util.Arrays;
class GFG {
static int maxWater( int height[], int n)
{
int max = 0 ;
int i = 0 , j = n - 1 ;
while (i < j) {
if (height[i] < height[j]) {
max = Math.max(max,
(j - i - 1 ) * height[i]);
i++;
}
else if (height[j] < height[i]) {
max = Math.max(max,
(j - i - 1 ) * height[j]);
j--;
}
else {
max = Math.max(max,
(j - i - 1 ) * height[i]);
i++;
j--;
}
}
return max;
}
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
def maxWater(height, n):
maximum = 0
i = 0
j = n - 1
while (i < j):
if (height[i] < height[j]):
maximum = max (maximum, (j - i - 1 ) * height[i])
i + = 1
elif (height[j] < height[i]):
maximum = max (maximum, (j - i - 1 ) * height[j])
j - = 1
else :
maximum = max (maximum, (j - i - 1 ) * height[i])
i + = 1
j - = 1
return maximum
height = [ 2 , 1 , 3 , 4 , 6 , 5 ]
n = len (height)
print (maxWater(height, n))
|
C#
using System;
class GFG {
static int maxWater( int [] height, int n)
{
int max = 0;
int i = 0, j = n - 1;
while (i < j) {
if (height[i] < height[j]) {
max = Math.Max(max,
(j - i - 1) * height[i]);
i++;
}
else if (height[j] < height[i]) {
max = Math.Max(max,
(j - i - 1) * height[j]);
j--;
}
else {
max = Math.Max(max,
(j - i - 1) * height[i]);
i++;
j--;
}
}
return max;
}
static public void Main()
{
int [] height = { 2, 1, 3, 4, 6, 5 };
int n = height.Length;
Console.Write(maxWater(height, n));
}
}
|
Javascript
<script>
function maxWater(height, n)
{
var maximum = 0;
var i = 0, j = n - 1;
while (i < j)
{
if (height[i] < height[j])
{
maximum = Math.max(maximum, (j - i - 1) * height[i]);
i++;
}
else if (height[j] < height[i])
{
maximum = Math.max(maximum, (j - i - 1) * height[j]);
j--;
}
else
{
maximum = Math.max(maximum, (j - i - 1) * height[i]);
i++;
j--;
}
}
return maximum;
}
var height = [ 2, 1, 3, 4, 6, 5 ];
var n = height.length;
document.write(maxWater(height, n))
</script>
|
Time Complexity: O(N)
Auxiliary Space: O(1)
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!
Last Updated :
15 Feb, 2023
Like Article
Save Article