Intuition
- Naively, notice that in order to fill water into a space, the left and right of that space must contain that height. We can check for the left bar with the maximum height, and the right bar with the maximum height on each iteration. We know that we can fill to the minimum of those two on each index.
- Notice how we are repeating a lot of calculations with the naive approach. Therefore, use memoization and DP to store the sub-computations.
- This still takes extra space. Therefore, use two pointers. Notice that on each index, if the left bar with maximum height is less than the right bar with maximum height to the right, then the bottleneck is the left, and vice versa otherwise.
Complexity
Runtime
Space
- with two pointers, otherwise
Code
Two Pointers
class Solution:
def trap(self, height: List[int]) -> int:
left, right = 0, len(height) - 1
left_max, right_max = 0, 0
water = 0
while left < right:
if height[left] < height[right]:
left_max = max(left_max, height[left])
if height[left] < left_max:
water += left_max - height[left]
left += 1
else:
right_max = max(right_max, height[right])
if height[right] < right_max:
water += right_max - height[right]
right -= 1
return waterMemoization + DP
class Solution:
def trap(self, height: List[int]) -> int:
max_l = height[0]
@cache
def r(i):
if i >= len(height):
return -1
return max(height[i], r(i + 1))
water = 0
for i in range(1, len(height) - 1):
max_l = max(max_l, height[i - 1])
max_r = r(i + 1)
min_boundary = min(max_l, max_r)
if height[i] < min_boundary:
water += min_boundary - height[i]
return waterTLE
class Solution:
def trap(self, height: List[int]) -> int:
water = 0
for i in range(1, len(height) - 1):
max_l = max(height[:i])
max_r = max(height[i + 1:])
min_boundary = min(max_l, max_r)
if height[i] < min_boundary:
water += min_boundary - height[i]
return waterNotes
Cards
START Basic Front: Trapping Rain Water Back: Check left and right boundaries END