2

Given an integer array which represents the heights of adjacent vertical bars standing on the ground.


The width of each bar is 1. Now you have to pick two bars and remove the bars between them such that when rain falls the water collected between two bars is maximum. Note that the distance between bars remains the same after removing the remaining bars.

eg:
1. [10,5,6,12,14] ans: 30 (10*3)
2. [3 16 10 5 6 12 20 18] ans: 80 (16*(number of integers between 16 and 18)).

There is a naive O(N2) solution but can we do better?

Kara
  • 6,115
  • 16
  • 50
  • 57
cold_coder
  • 584
  • 4
  • 8
  • 24

1 Answers1

6

This problem can be solved using stack but there is a better and simpler solution using two pointer method.

Here is the pseudocode:

result := 0
left := 0
right := n - 1
while(left < right):
    result := max(result, (right - left - 1) * min(arr[left], arr[right]))
    if(arr[left] <= arr[right]):
        left := left + 1
    else:
        right := right - 1
    endif
end

Explanation

Start from leftmost and rightmost position of the bars and gradually walk opposite direction based on some decision until the two pointers is not crossing each other.

When arr[left] <= arr[right], we will go right by left := left + 1 because there is no way to get better height keeping arr[left] as left boundary. And if we would move to left by right := right - 1 in this case, there would be no possibility to get larger area across width as the width would reduce while the height would be still arr[left].

Similar logic for arr[right] < arr[left].

The time complexity is O(n) and space is O(1).

Hope it helps!

Kaidul
  • 15,409
  • 15
  • 81
  • 150