From ea19828ef34248590f42c2d07f4278bf83cecad5 Mon Sep 17 00:00:00 2001 From: Sangeeth Sudheer Date: Sun, 24 Apr 2022 00:07:42 +0530 Subject: [PATCH] trapping-rain-water py3 --- .../python3/extra_space.py | 61 +++++++++++++++++++ 0042_trapping-rain-water/python3/solution.py | 48 +++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 0042_trapping-rain-water/python3/extra_space.py diff --git a/0042_trapping-rain-water/python3/extra_space.py b/0042_trapping-rain-water/python3/extra_space.py new file mode 100644 index 0000000..8699651 --- /dev/null +++ b/0042_trapping-rain-water/python3/extra_space.py @@ -0,0 +1,61 @@ +# Time: O(N) +# Space: O(N) + +class Solution: + def trap(self, heights: List[int]) -> int: + if len(heights) < 2: return 0 + + # For every ith height, we need to calculate the max height + # on left and max on right of it + max_lefts, max_rights = [0] * len(heights), [0] * len(heights) + + maxl = 0 + for i in range(len(heights)): + max_lefts[i] = maxl + maxl = max(maxl, heights[i]) + + maxr = 0 + for j in range(len(heights) - 1, -1, -1): + max_rights[j] = maxr + maxr = max(maxr, heights[j]) + + print(max_lefts) + print(max_rights) + + # For every ith height, we can now compute the water output it can hold + # by doing the following: + # + # min(max_height_to_left, max_height_to_right) - height_of_bar + # + # If we ignore height_of_bar for a moment, the amount of water that can be + # held would be constrained by the least heights out of left/right. + # + # 3 + # 2 | + # | | + # | 0 | + # + # In the above case, would be min(2, 3) == 2. But, if we fill the space up with a bar + # then: + # + # 3 + # 2 | + # | 1 | + # | | | + # + # We can't put 2 water units. We need to subtract the height of the bar from the prev + # min() which will give us 1. + # + # NOTE: We need to do this for every ith height in the array. + + output = 0 + for i, h in enumerate(heights): + value = min(max_lefts[i], max_rights[i]) - heights[i] + + # It's possible that ith height is very large, causing + # the expression above to give us -ve value. In this case + # we just ignore it (i.e, 0 output for this ith height) + if value > 0: + output += value + + return output diff --git a/0042_trapping-rain-water/python3/solution.py b/0042_trapping-rain-water/python3/solution.py index e69de29..274081b 100644 --- a/0042_trapping-rain-water/python3/solution.py +++ b/0042_trapping-rain-water/python3/solution.py @@ -0,0 +1,48 @@ +# 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