Update 0084.柱状图中最大的矩形.md

补全所有python解法,补充comment
This commit is contained in:
Asterisk
2021-09-30 16:32:53 +08:00
committed by GitHub
parent 33768a0ffb
commit 5a37bed135

View File

@ -281,52 +281,137 @@ class Solution {
Python:
动态规划
```python3
# 双指针暴力解法leetcode超时
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
result = 0
minleftindex, minrightindex = [0]*len(heights), [0]*len(heights)
# 从左向右遍历:以每一根柱子为主心骨(当前轮最高的参照物),迭代直到找到左侧和右侧各第一个矮一级的柱子
res = 0
minleftindex[0]=-1
for i in range(1,len(heights)):
t = i-1
while t>=0 and heights[t]>=heights[i]: t=minleftindex[t]
minleftindex[i]=t
for i in range(len(heights)):
left = i
right = i
# 向左侧遍历:寻找第一个矮一级的柱子
for _ in range(left, -1, -1):
if heights[left] < heights[i]:
break
left -= 1
# 向右侧遍历:寻找第一个矮一级的柱子
for _ in range(right, len(heights)):
if heights[right] < heights[i]:
break
right += 1
minrightindex[-1]=len(heights)
for i in range(len(heights)-2,-1,-1):
t=i+1
while t<len(heights) and heights[t]>=heights[i]: t=minrightindex[t]
minrightindex[i]=t
width = right - left - 1
height = heights[i]
res = max(res, width * height)
for i in range(0,len(heights)):
left = minleftindex[i]
right = minrightindex[i]
summ = (right-left-1)*heights[i]
result = max(result,summ)
return result
```
单调栈 版本二
```python3
return res
# DP动态规划
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
heights.insert(0,0) # 数组头部加入元素0
heights.append(0) # 数组尾部加入元素0
st = [0]
size = len(heights)
# 两个DP数列储存的均是下标index
min_left_index = [0] * size
min_right_index = [0] * size
result = 0
# 记录每个柱子的左侧第一个矮一级的柱子的下标
min_left_index[0] = -1 # 初始化防止while死循环
for i in range(1, size):
# 以当前柱子为主心骨,向左迭代寻找次级柱子
temp = i - 1
while temp >= 0 and heights[temp] >= heights[i]:
# 当左侧的柱子持续较高时尝试这个高柱子自己的次级柱子DP
temp = min_left_index[temp]
# 当找到左侧矮一级的目标柱子时
min_left_index[i] = temp
# 记录每个柱子的右侧第一个矮一级的柱子的下标
min_right_index[size-1] = size # 初始化防止while死循环
for i in range(size-2, -1, -1):
# 以当前柱子为主心骨,向右迭代寻找次级柱子
temp = i + 1
while temp < size and heights[temp] >= heights[i]:
# 当右侧的柱子持续较高时尝试这个高柱子自己的次级柱子DP
temp = min_right_index[temp]
# 当找到右侧矮一级的目标柱子时
min_right_index[i] = temp
for i in range(size):
area = heights[i] * (min_right_index[i] - min_left_index[i] - 1)
result = max(area, result)
return result
# 单调栈
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
# Monotonic Stack
'''
找每个柱子左右侧的第一个高度值小于该柱子的柱子
单调栈:栈顶到栈底:从大到小(每插入一个新的小数值时,都要弹出先前的大数值)
栈顶,栈顶的下一个元素,即将入栈的元素:这三个元素组成了最大面积的高度和宽度
情况一当前遍历的元素heights[i]大于栈顶元素的情况
情况二当前遍历的元素heights[i]等于栈顶元素的情况
情况三当前遍历的元素heights[i]小于栈顶元素的情况
'''
# 输入数组首尾各补上一个0与42.接雨水不同的是,本题原首尾的两个柱子可以作为核心柱进行最大面积尝试
heights.insert(0, 0)
heights.append(0)
stack = [0]
result = 0
for i in range(1, len(heights)):
while st!=[] and heights[i]<heights[st[-1]]:
midh = heights[st[-1]]
st.pop()
if st!=[]:
minrightindex = i
minleftindex = st[-1]
summ = (minrightindex-minleftindex-1)*midh
result = max(summ,result)
st.append(i)
# 情况一
if heights[i] > heights[stack[-1]]:
stack.append(i)
# 情况二
elif heights[i] == heights[stack[-1]]:
stack.pop()
stack.append(i)
# 情况三
else:
# 抛出所有较高的柱子
while stack and heights[i] < heights[stack[-1]]:
# 栈顶就是中间的柱子,主心骨
mid_index = stack[-1]
stack.pop()
if stack:
left_index = stack[-1]
right_index = i
width = right_index - left_index - 1
height = heights[mid_index]
result = max(result, width * height)
stack.append(i)
return result
# 单调栈精简
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
```
*****
JavaScript:
```javascript