Description Imagine a histogram (bar graph). Design an algorithm to compute the volume of water it could hold if someone poured water across the top. You can assume that each histogram bar has width 1.
The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of water (blue section) are being trapped. Thanks Marcos for contributing this image!
Example:
Input: [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6 Solutions Solution 1 Thinking
Trapping rain on a histogram. Scanning bounds per bar can be quadratic.
Water at \(i\) is the min of the tallest bars on each side minus \(height[i]\) ; those extrema can be precomputed.
\(left[i]\) and \(right[i]\) are inclusive prefix/suffix maxima; sum \(\min(l,r)-h\) . Length less than \(3\) stores nothing.
Python3 Java C++ Go TypeScript C# Swift
class Solution :
def trap ( self , height : List [ int ]) -> int :
n = len ( height )
if n < 3 :
return 0
left = [ height [ 0 ]] * n
right = [ height [ - 1 ]] * n
for i in range ( 1 , n ):
left [ i ] = max ( left [ i - 1 ], height [ i ])
right [ n - i - 1 ] = max ( right [ n - i ], height [ n - i - 1 ])
return sum ( min ( l , r ) - h for l , r , h in zip ( left , right , height ))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 class Solution {
public int trap ( int [] height ) {
int n = height . length ;
if ( n < 3 ) {
return 0 ;
}
int [] left = new int [ n ] ;
int [] right = new int [ n ] ;
left [ 0 ] = height [ 0 ] ;
right [ n - 1 ] = height [ n - 1 ] ;
for ( int i = 1 ; i < n ; ++ i ) {
left [ i ] = Math . max ( left [ i - 1 ] , height [ i ] );
right [ n - i - 1 ] = Math . max ( right [ n - i ] , height [ n - i - 1 ] );
}
int ans = 0 ;
for ( int i = 0 ; i < n ; ++ i ) {
ans += Math . min ( left [ i ] , right [ i ] ) - height [ i ] ;
}
return ans ;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 class Solution {
public :
int trap ( vector < int >& height ) {
int n = height . size ();
if ( n < 3 ) {
return 0 ;
}
int left [ n ], right [ n ];
left [ 0 ] = height [ 0 ];
right [ n - 1 ] = height [ n - 1 ];
for ( int i = 1 ; i < n ; ++ i ) {
left [ i ] = max ( left [ i - 1 ], height [ i ]);
right [ n - i - 1 ] = max ( right [ n - i ], height [ n - i - 1 ]);
}
int ans = 0 ;
for ( int i = 0 ; i < n ; ++ i ) {
ans += min ( left [ i ], right [ i ]) - height [ i ];
}
return ans ;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 func trap ( height [] int ) ( ans int ) {
n := len ( height )
if n < 3 {
return 0
}
left := make ([] int , n )
right := make ([] int , n )
left [ 0 ], right [ n - 1 ] = height [ 0 ], height [ n - 1 ]
for i := 1 ; i < n ; i ++ {
left [ i ] = max ( left [ i - 1 ], height [ i ])
right [ n - i - 1 ] = max ( right [ n - i ], height [ n - i - 1 ])
}
for i , h := range height {
ans += min ( left [ i ], right [ i ]) - h
}
return
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 function trap ( height : number []) : number {
const n = height . length ;
if ( n < 3 ) {
return 0 ;
}
const left : number [] = new Array ( n ). fill ( height [ 0 ]);
const right : number [] = new Array ( n ). fill ( height [ n - 1 ]);
for ( let i = 1 ; i < n ; ++ i ) {
left [ i ] = Math . max ( left [ i - 1 ], height [ i ]);
right [ n - i - 1 ] = Math . max ( right [ n - i ], height [ n - i - 1 ]);
}
let ans = 0 ;
for ( let i = 0 ; i < n ; ++ i ) {
ans += Math . min ( left [ i ], right [ i ]) - height [ i ];
}
return ans ;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 public class Solution {
public int Trap ( int [] height ) {
int n = height . Length ;
if ( n < 3 ) {
return 0 ;
}
int [] left = new int [ n ];
int [] right = new int [ n ];
left [ 0 ] = height [ 0 ];
right [ n - 1 ] = height [ n - 1 ];
for ( int i = 1 ; i < n ; ++ i ) {
left [ i ] = Math . Max ( left [ i - 1 ], height [ i ]);
right [ n - i - 1 ] = Math . Max ( right [ n - i ], height [ n - i - 1 ]);
}
int ans = 0 ;
for ( int i = 0 ; i < n ; ++ i ) {
ans += Math . Min ( left [ i ], right [ i ]) - height [ i ];
}
return ans ;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 class Solution {
func trap ( _ height : [ Int ]) -> Int {
let n = height . count
if n < 3 {
return 0
}
var left = [ Int ]( repeating : 0 , count : n )
var right = [ Int ]( repeating : 0 , count : n )
left [ 0 ] = height [ 0 ]
right [ n - 1 ] = height [ n - 1 ]
for i in 1. .< n {
left [ i ] = max ( left [ i - 1 ], height [ i ])
}
for i in stride ( from : n - 2 , through : 0 , by : - 1 ) {
right [ i ] = max ( right [ i + 1 ], height [ i ])
}
var ans = 0
for i in 0. .< n {
ans += min ( left [ i ], right [ i ]) - height [ i ]
}
return ans
}
}
GitHub