https://leetcode-cn.com/probl...
会超时的方法:
双重循环
最简单的思路,时间复杂度 O(n^2) 会超时(最后附超时代码)
分治算法
先找到当前数组中最小元素。
那么答案将在一下三种情况中:
- 包含最小元素,那么高度是最小元素高度,长度是整个区间
- 不包含最小元素,且在最下元素左边 (递归左半区间)
- 不包含最小元素,且在最下元素有边 (递归右半区间)
这个方法的平均时间复杂度是 O(nlogn)
但是最坏情况时间复杂度仍是 O(n^2) 也会超时(最后附超时代码)
正确解法
从前向后遍历,过程中维护一个递增的栈。
如果下一个大于栈顶元素,就直接入栈。
如果小于,就把栈里大的元素都弹出来,并且计算高度是弹出的元素高度,宽度是当前元素到栈顶元素之间。
为什么可以以弹出元素高度为高度,当前位置和栈顶元素位置间的距离为宽度呢?因为栈是递增的,比弹出元素高度低的元素一定都在栈里,栈顶一定是离这个元素最近的一个(高度小于该元素的元素)换句话就是它们之间的元素高度都大于该元素。
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
hs = [0] + heights + [0]
s = []
ans = 0
for i, h in enumerate(hs):
while s and hs[s[-1]] > h:
j = s.pop()
ans = max(ans, hs[j] * (i-s[-1]-1))
s.append(i)
return ans
超时代码
超时代码一 双重循环
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
maxa = 0
for i in range(len(heights)):
minh = heights[i]
for j in range(i, len(heights)):
minh = min(minh, heights[j])
maxa = max(maxa, minh * (j-i+1))
return maxa
超时代码二 分治
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
def solve(l, r, d):
if l >= r: return 0
if l == r-1: return heights[l]
min_i = l
min_h = heights[l]
for i, h in enumerate(heights[1+l:r]):
if h < min_h:
min_h = h
min_i = i+l+1
return max(min_h * (r - l), solve(l, min_i, d+1), solve(min_i+1, r, d+1))
return solve(0, len(heights), 0)
欢迎来我的博客: https://codeplot.top/
我的博客刷题分类:https://codeplot.top/categories/%E5%88%B7%E9%A2%98/
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。