給定 n 個非負整數,用來表示柱狀圖中各個柱子的高度。每個柱子彼此相鄰,且寬度為 1 。求在該柱狀圖中,能夠勾勒出來的矩形的最大面積。
以上是柱狀圖的示例,其中每個柱子的寬度為 1,給定的高度為 [2,1,5,6,2,3]。
圖中陰影部分為所能勾勒出的最大矩形面積,其面積為 10 個單位。
示例:
輸入: [2,1,5,6,2,3]
輸出: 10
思路
- 暴力枚舉。
兩個柱子間矩形的高由他們之間最矮的柱子決定。在枚舉矩形的時候,首先是枚舉底長[i:j+1],然后在底長范圍中找到最低高度min(heights[i:j+1]),底長和最低高度相乘計算面積。
時間復雜度O(n**3),空間復雜度O(1)。
def largestRectangleArea(self, heights: List[int]) -> int:
if len(heights)== 0:
return 0
if len(heights) == 1:
return heights[0]
max_area = 0
for i in range(len(heights)):
for j in range(i, len(heights)):
sub = heights[i:j+1]
area = (j-i+1) * min(sub)
max_area = max(max_area, area)
return max_area
- 分治法。
以最小高度為中心,將區域分為3份,區間的最大面積為
max(
最小高度 * 區間長度,
最小高度左邊最大面積,
最小高度右邊最大面積
)
def largestRectangleArea(self, heights: List[int]) -> int:
def devide(left, right):
if right < left:
return 0
min_index = left
for i in range(left, right + 1):
if heights[i] < heights[min_index]:
min_index = i
return max((right-left+1)*heights[min_index], devide(left, min_index-1), devide(min_index+1, right))
if len(heights) == 0:
return 0
if len(heights) == 1:
return heights[0]
return devide(0, len(heights)-1)
以上兩種方法,使用python均超時
- 棧
維護一個棧,初始化將 -1入棧。
遍歷heights數組,如果heights[i] > heights[i-1],即heights[i]大于棧頂元素,則下標i入棧;
如果heights[i]<heights[i-1],開始將棧頂元素彈出,直到遇到棧頂元素小于heights[i];
每次彈出下標計算的面積為:
(棧頂元素的左邊界永遠是棧內它的下一個元素, 右邊界是遇到的比它小的第一個元素)
以棧頂元素為高 * 右邊界到左邊界之間的矩形為寬
即: heights[stack[top]] x (i - stack[top - 1] -1)
當達到數組尾部時,將棧中剩余元素全部彈出棧,在彈出時計算面積的公式為:
heights[stack[top]] x (heights.length - stack[top-1] - 1)
def largestRectangleArea(self, heights: List[int]) -> int:
if len(heights) == 0:
return 0
if len(heights) == 1:
return heights[0]
stack = [-1]
max_area = 0
for i in range(len(heights)):
while stack[-1] != -1 and heights[i] < heights[stack[-1]]:
h = stack.pop()
area = heights[h] * (i - stack[-1] - 1)
max_area = max(max_area, area)
stack.append(i)
while stack[-1] != -1:
h = stack.pop()
area = heights[h] * (len(heights) - stack[-1] - 1)
max_area = max(max_area, area)
return max_area