2022-04-23 18:37:42 +00:00
|
|
|
# Time: O(N)
|
|
|
|
# Space: O(N)
|
|
|
|
|
|
|
|
class Solution:
|
|
|
|
def trap(self, heights: List[int]) -> int:
|
|
|
|
# Two pointer approach
|
|
|
|
left, right = 0, len(heights) - 1
|
|
|
|
|
|
|
|
# Since while scanning the array, at a given index i, we
|
|
|
|
# only need to consider the minimum of max_left_heights and
|
|
|
|
# max_right_heights, we just need to keep moving from both
|
|
|
|
# ends and keep track of the maximum height seen so far. We
|
|
|
|
# can then compare these two heights and decide from which
|
|
|
|
# side to move next.
|
|
|
|
max_left = max_right = 0
|
|
|
|
|
|
|
|
output = 0
|
|
|
|
while left <= right:
|
|
|
|
# By the formula from the DP approach:
|
|
|
|
#
|
|
|
|
# min(max_left, max_right) - heights[i]
|
|
|
|
#
|
|
|
|
# If max_left <= max_right, formula becomes:
|
|
|
|
#
|
|
|
|
# max_left - heights[i]
|
|
|
|
#
|
|
|
|
if max_left <= max_right:
|
|
|
|
# Shorter form to avoid -ve values
|
|
|
|
output += max(max_left - heights[left], 0)
|
|
|
|
|
|
|
|
max_left = max(max_left, heights[left])
|
|
|
|
left += 1
|
|
|
|
# By the formula from the DP approach:
|
|
|
|
#
|
|
|
|
# min(max_left, max_right) - heights[i]
|
|
|
|
#
|
|
|
|
# If max_left > max_right, formula becomes:
|
|
|
|
#
|
|
|
|
# max_right - heights[i]
|
|
|
|
#
|
|
|
|
else:
|
|
|
|
output += max(max_right - heights[right], 0)
|
|
|
|
|
|
|
|
max_right = max(max_right, heights[right])
|
|
|
|
right -= 1
|
|
|
|
|
|
|
|
|
|
|
|
return output
|