tasks for today:
1. 42.接雨水
2. 84.柱状图中最大矩形
----------------------------------------------------------------------
1. 42.接雨水
method 1: finding the right max and left max of each element, chose the min(rightmax, leftmax), then deduct the element height would be the water for each element.
In this code, the left-firstbigger and right-firstbigger list are derived, and then the left-max and right-max list are derived based on those. and then calculate the held water one by one.
class Solution:
def trap(self, height: List[int]) -> int:
if len(height) <= 2: return 0
rightBigger = self.findBigger(height)
leftBigger = self.findBigger(list(reversed(height)))
# print(rightBigger)
# print(list(reversed(leftBigger)))
for i in range(len(height)):
if rightBigger[i] != -1:
rightBigger[i] = max(rightBigger[i:])
if leftBigger[i] != -1:
leftBigger[i] = max(leftBigger[i:])
leftBigger = list(reversed(leftBigger))
# print(rightBigger)
# print(leftBigger)
volume = 0
# result = []
for i in range(len(height)):
# result.append(max(min(leftBigger[i], rightBigger[i]) - height[i], 0))
volume += max(min(leftBigger[i], rightBigger[i]) - height[i], 0)
# print(result)
return volume
# noted: this function find the first bigger one in right hand side, instead of the biggest one
def findBigger(self, nums):
result = [-1] * len(nums)
monStack = [0]
for i in range(1, len(nums)):
if nums[i] <= nums[monStack[-1]]:
monStack.append(i)
else:
while len(monStack) != 0 and nums[i] > nums[monStack[-1]]:
eleInd = monStack.pop()
result[eleInd] = nums[i]
monStack.append(i)
return result
method 2: this is simlified, bacause the held water is calculated along with the process of monoStack.
class Solution:
def trap(self, height: List[int]) -> int:
if len(height) <= 2: return 0
nums = copy.deepcopy(height)
monStack = [0]
volume = 0
for i in range(1, len(nums)):
if nums[i] < nums[monStack[-1]]:
monStack.append(i)
elif nums[i] == nums[monStack[-1]]:
monStack.pop()
monStack.append(i)
else:
while len(monStack) != 0 and nums[i] > nums[monStack[-1]]:
eleInd = monStack.pop()
Curstep = height[eleInd]
if monStack:
Curheight = min(nums[monStack[-1]], nums[i]) - Curstep
width = i - monStack[-1] - 1
volume += width * Curheight
monStack.append(i)
return volume
Note: the method 1's essense is calculatiing all the held water by traversing each vertical volume, while the method 2' essense is calculating all the held water by traversing each horizontal volume.
Therefore, the method 1 does not require width calculation, while method 2 requires width calculation.
2. 84.柱状图中最大矩形
This practice is a reverse version of the practice 42, which is reflected by the sequence of the index's represented value in heights. In this practice, the order in monoStack should be descending from top of stack to the bottom of the stack.
The main strcuture for this code snippet is the same with the method 2 in practice 42, which is calculating vertical volumn, but in this practice, it is not the addition that is wanted, instead, the max is wanted.
Be noted that, in this practice, how to handle the bound is different from the practice 42, which requires complement in both side of the height list with a zero as a place holder, for more convinently dealing with the both sides' bars, which may potentially be a max size area candidate.
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
if len(heights) == 1: return heights[0]
heights.insert(0, 0)
heights.append(0)
monoStack = [0]
result = 0
for i in range(1, len(heights)):
if heights[i] > heights[monoStack[-1]]:
monoStack.append(i)
elif heights[i] == heights[monoStack[-1]]:
monoStack.pop()
monoStack.append(i)
else:
while monoStack and heights[i] < heights[monoStack[-1]]:
eleInd = monoStack.pop()
curstep = heights[eleInd]
if monoStack:
left = monoStack[-1]
right = i
width = right - left - 1
result = max(result, width * curstep)
monoStack.append(i)
return result