题目:
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
解答:
方法一:双指针法,使用left,right两个指针分别统计:当前柱子左侧/右侧 第一个低于当前柱子的高度,超时
时间复杂度:O(n^2)
空间复杂度:O(1)
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
#双指针法
n=len(heights)
res=max(heights)
for i in range(n):
lflag=False
rflag=False
#寻找当前柱子 左侧第一个低于该柱子的高度
for left in range(i,-1,-1):
if heights[left]<heights[i]:
lflag=True
break
#寻找当前柱子 右侧第一个低于该柱子的高度
for right in range(i,n):
if heights[right]<heights[i]:
rflag=True
break
#当前柱子最低
if (not lflag) and (not rflag):
w=n
elif lflag and rflag:
w=right-left-1
else:
w=right-left
res=max(res,w*heights[i])
return res
方法二:动态规划
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
#动态规划法
n=len(heights)
res=max(heights)
#left_idx:记录每个柱子 左边第一个小于该柱子的下标
left_idx=[-1]*n
for i in range(1,n):
t=i-1
while t>=0 and heights[t]>=heights[i]:
t=left_idx[t]
if t>=0:
left_idx[i]=t
#print(left_idx)
#right_idx:记录每个柱子 右边第一个小于该柱子的下标
right_idx=[n]*n
for i in range(n-2,-1,-1):
t=i+1
while t<n and heights[t]>=heights[i]:
t=right_idx[t]
if t<n:
right_idx[i]=t
#print(right_idx)
for i in range(n):
#当前柱子左右两侧皆不存在 比其低的柱子,当前柱子最低
if left_idx[i]==-1 and right_idx[i]==n:
w=n
#当前柱子左右两侧皆存在 比其低的柱子
elif left_idx[i]!=-1 and right_idx[i]!=n:
w=right_idx[i]-left_idx[i]-1
else:
w=right_idx[i]-left_idx[i]-1
res=max(res,w*heights[i])
return res
方法三:单调栈
- 栈顶到栈底单调递减
- 只有栈里从大到小的顺序,才能保证栈顶元素找到左右两边第一个小于栈顶元素的柱子
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
heights.insert(0, 0)
heights.append(0)
stack = [0]
result = 0
n=len(heights)
for i in range(1, n):
while stack and heights[i] < heights[stack[-1]]:
mid=stack.pop()
if stack:
# area = width * height
area = (i - stack[-1] - 1) *heights[mid]
result = max(area, result)
stack.append(i)
return result