from typing import List
# 暴力解法(leetcode超时)classSolution:deftrap(self, height: List[int])->int:# 按照列来计算体积
n =len(height)if n <=2:return0
result =0# i = 0, n-1, 开始和最后位置无法积水for i inrange(1, n-1):
lHeight = height[i]
rHeight = height[i]# 左边for j inrange(i-1,-1,-1):if lHeight < height[j]:
lHeight = height[j]# 右边for j inrange(i+1, n):if rHeight < height[j]:
rHeight = height[j]
h =min(lHeight, rHeight)- height[i]# 左侧 右侧高度----你需要什么print(height[:i], height[i], height[i+1:])print(i, height[i], lHeight, rHeight,h)print('\n')if h >0:
result += h
return result
# height = [0,1,0,2,1,0,1,3,2,1,2,1]# c = Solution().trap(height)
双指针
# 双指针classSolution:deftrap(self, height: List[int])->int:# 按照列来计算体积
n =len(height)if n <=2:return0
result =0# i = 0, n-1, 开始和最后位置无法积水
max_left_height =[0for _ inrange(n)]
max_right_height =[0for _ inrange(n)]
max_left_height[0]= height[0]for i inrange(1, n):
max_left_height[i]=max(max_left_height[i -1], height[i])
max_right_height[n -1]= height[n -1]## 防止右边溢出for i inrange(n -2,-1,-1):
max_right_height[i]=max(max_right_height[i +1], height[i])for i inrange(1, n -1):
h =min(max_left_height[i], max_right_height[i])- height[i]print(i, height[:i], height[i], height[i +1:])print(max_left_height[i], max_right_height[i], h)if h >0: result += h
return result
模拟过程
[0,1,0,2,2,1,0,1,3,2,1,2,1]
————————————————————————————————————————————
0
————————————————————————————————————————————
开始和结束无法积水
i=1, height[1]> height[stack[-1]], stack.pop(), stack.append(i)-- 还要待考虑
————————————————————————————————————————————
1
————————————————————————————————————————————
i=2,height[2]=0< height[stack[-1]] stack.append(i)
————————————————————————————————————————————
12
————————————————————————————————————————————
开始和结束无法积水
i=3, height[3]=2> height[stack[-1]]=0, mid = stack.pop(), left = stack[-1], width = i - stack[-1]-1, h =min(height[stack[-1]], height[i])- height[i]if h >0: res += h
i=3, height[3]=2> height[stack[-1]]=0, mid = stack.pop()=2, left = stack[-1]=1, width = i - stack[-1]-1=3-1-1=1, h =min(height[stack[-1]], height[i])- height[mid]=min(1,2)-0=1
————————————————————————————————————————————
1
————————————————————————————————————————————
if mid = stack.pop()=1, 则没有left = stack[-1] 会报错
所以对于上面的计算需要有前提
while stack and height[i]> height[stack[-1]]:
mid = stack.pop()if stack:
left = stack[-1]
width = i - left -1
heighty =min(height[left], height[i])- height[mid]
res += width * heighty
stack.append(i)
————————————————————————————————————————————
3
————————————————————————————————————————————
i =4, height[4]=2= height[stack[-1]], 此时应该把第一个 2 取出,使用右边 2 高度进行接下来的统计
————————————————————————————————————————————
4
————————————————————————————————————————————
## [0, 1, 0, 2, 2, 1, 0, 1, 3, 2, 1, 2, 1]
i =5, height[5]=1< height[stack[-1]], 加入
if height[i]< height[stack[-1]]: stack.append(i)
————————————————————————————————————————————
45
————————————————————————————————————————————
i =6, height[5]=0< height[stack[-1]], 加入
if height[i]< height[stack[-1]]: stack.append(i)
————————————————————————————————————————————
456
————————————————————————————————————————————
i =7, height[7]=1> height[stack[-1]],if mid = stack.pop()=1, 则没有left = stack[-1] 会报错
所以对于上面的计算需要有前提
while stack and height[i]> height[stack[-1]]:
mid = stack.pop()if stack:
left = stack[-1]
width = i - left -1
heighty =min(height[left], height[i])- height[mid]
res += width * heighty
stack.append(i)
————————————————————————————————————————————
45
————————————————————————————————————————————
mid =6, left =5, width =7-5-1=1, heighty=min(1,1)-0=1; res +=1
————————————————————————————————————————————
45
————————————————————————————————————————————
## [0, 1, 0, 2, 2, 1, 0, 1, 3, 2, 1, 2, 1]
mid =5, left =4, width=7-4-1=2, height=min(2,1)-1=0, res +=0
————————————————————————————————————————————
4
————————————————————————————————————————————
mid =4, 没有left, stop, 加入i
————————————————————————————————————————————
————————————————————————————————————————————
加入i
————————————————————————————————————————————
7
————————————————————————————————————————————
## [0, 1, 0, 2, 2, 1, 0, 1, 3, 2, 1, 2, 1][0,1,2,3,4,5,6,7,8,9,10,11,12]
i=8while stack and height[i]> height[stack[-1]]:
mid = stack.pop()if stack:
left = stack[-1]
width = i - left -1
heighty =min(height[left], height[i])- height[mid]
res += width * heighty
stack.append(i)
mid = stack.pop()=7, left = 没有, 加入 i
————————————————————————————————————————————
————————————————————————————————————————————
加入i
————————————————————————————————————————————
8
————————————————————————————————————————————
i =9,val=2< height[stack[-1]]=3, 加入i
加入i
————————————————————————————————————————————
89
————————————————————————————————————————————
i =10,val=1< height[stack[-1]]=2, 加入i
加入i
————————————————————————————————————————————
8910
————————————————————————————————————————————
## [0, 1, 0, 2, 2, 1, 0, 1, 3, 2, 1, 2, 1][0,1,2,3,4,5,6,7,8,9,10,11,12]
i =11while stack and height[i]> height[stack[-1]]:
mid = stack.pop()if stack:
left = stack[-1]
width = i - left -1
heighty =min(height[left], height[i])- height[mid]
res += width * heighty
stack.append(i)
————————————————————————————————————————————
89
————————————————————————————————————————————
mid =10, left =9, width = i - left -1=11-9-1=1, heighty=min(2,2)-height[mid]=2-1=1, h=1*1=1
————————————————————————————————————————————
8
————————————————————————————————————————————
mid =9, left =8, width = xxx
mid =8, left ='没有',
————————————————————————————————————————————
————————————————————————————————————————————
————————————————————————————————————————————
11
————————————————————————————————————————————
i=12,< tack[-1]对应的值, stop。
单调栈
classSolution:deftrap(self, height: List[int])->int:
result =0
stack =[0]
n =len(height)for i inrange(1, n):if height[i]< height[stack[-1]]:
stack.append(i)print('if <', stack)elif height[i]== height[stack[-1]]:
stack.pop()
stack.append(i)print('elif ==', stack)else:print(i, stack[-1])while stack and height[i]> height[stack[-1]]:print('1 else stack', stack)
mid = stack.pop()print('xx')if stack:print('else, stack.pop()', stack, mid, stack[-1])
left = stack[-1]
width = i - left -1
heighty =min(height[left], height[i])- height[mid]
result += width * heighty
print(width * heighty,'hh')
stack.append(i)print('1 else stack add', stack)return result
# height = [0, 1, 0, 2, 1, 0, 1, 3, 2, 2, 1, 2, 1]# index = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
height=[3,2,1,2,3]
c = Solution().trap(height)
从我自己出发, 找左边第一个小于heights[i]的位置
右边第一个小于heights[i]的位置, 面积的width = right - left -1
之后面积 = width * heights[i]
一个一个的找。就能找到最大的面积。
from typing import List
classSolution:deflargestRectangleArea(self, heights: List[int])->int:
stack =[-1]
n =len(heights)
area =0for i inrange(0, n):if heights[i]> heights[stack[-1]]:
stack.append(i)if heights[i]== heights[stack[-1]]:
stack.pop()
stack.append(i)else:whilelen(stack)>=2and heights[i]< heights[stack[-1]]:
mid = stack.pop()
right = i
left = stack[-1]
area =max(area,(right - left -1)* heights[mid])
stack.append(i)whilelen(stack)>=2:
mid = stack.pop()
right = n
left = stack[-1]
area =max(area,(right - left -1)* heights[mid])return area
heights =[2,1,5,6,2,3]
c = Solution().largestRectangleArea(heights)
从我自己出发, 找左边第一个小于heights[i]的位置
右边第一个小于heights[i]的位置, 面积的width = right - left -1
之后面积 = width * heights[i]
一个一个的找。就能找到最大的面积。
from typing import List
## code python 单调栈
```py
classSolution:deflargestRectangleArea(self, heights: List[int])->int:
stack =[-1]
n =len(heights)
area =0for i inrange(0, n):if heights[i]> heights[stack[-1]]:
stack.append(i)if heights[i]== heights[stack[-1]]:
stack.pop()
stack.append(i)else:whilelen(stack)>=2and heights[i]< heights[stack[-1]]:
mid = stack.pop()
right = i
left = stack[-1]
area =max(area,(right - left -1)* heights[mid])
stack.append(i)whilelen(stack)>=2:
mid = stack.pop()
right = n
left = stack[-1]
area =max(area,(right - left -1)* heights[mid])return area
heights =[2,1,5,6,2,3]
c = Solution().largestRectangleArea(heights)
## code python 单调栈精简
```py
# 单调栈精简
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
heights.insert(0, 0)
heights.append(0)
stack = [0]
result = 0
for i in range(1, len(heights)):
while stack and heights[i] < heights[stack[-1]]:
mid_height = heights[stack[-1]]
stack.pop()
if stack:
# area = width * height
area = (i - stack[-1] - 1) * mid_height
result = max(area, result)
stack.append(i)
return result