1. 程式人生 > 實用技巧 >leetcode hot 100- 84. 柱狀圖中最大的矩形

leetcode hot 100- 84. 柱狀圖中最大的矩形

84. 柱狀圖中最大的矩形

思路一:暴力法

思路參考:https://leetcode-cn.com/problems/largest-rectangle-in-histogram/solution/bao-li-jie-fa-zhan-by-liweiwei1419/

列舉每個柱子為高度的最大矩形的面積

實現:對每個高度的柱子向兩邊擴張,試圖尋找以當前高度為矩形的最大寬度

 1 class Solution {
 2     public int largestRectangleArea(int[] heights) {
 3         
 4         // 對每個高度的柱子向兩邊擴張,試圖尋找以當前高度為矩形的最大寬度
5 int maxArea = 0; 6 int len = heights.length; 7 for(int i = 0; i < len; i++){ 8 int leftBorder = i-1; 9 for(; leftBorder >= 0 && heights[leftBorder] >= heights[i]; leftBorder--); 10 int rightBorder = i+1; 11 for
(; rightBorder < len && heights[rightBorder] >= heights[i]; rightBorder++); 12 maxArea = Math.max(maxArea, heights[i] * (rightBorder - leftBorder - 1)); 13 } 14 return maxArea; 15 } 16 }

leetcode執行用時:938 ms > 19.41%, 記憶體消耗:40.2 MB > 40.10%

複雜度分析:

時間複雜度:O(n2

)。雙層for迴圈,所以時間複雜度為O(n2)。

空間複雜度:O(1)。

思路二:遞減棧

遞減棧,從棧頂到棧底的序列是一個降序序列,遞減 如果當前高度大於棧頂下標對應的高度,直接入棧,否則迴圈出棧,直至當前高度大於棧頂高度或者棧為空,每次出棧一個元素,用當前下標減去出棧下標再減一,得到寬度,乘以出棧下標對應的元素,得出面積 計算寬度,如果棧為空,左邊界為0,右邊界為i,否則左邊界為棧頂下標,右邊界為陣列長度 一次遍歷之後,出棧棧中剩餘元素, 出棧過程中如果當前出棧的元素等於棧頂下標對應的元素,持續出棧,直到棧頂下標元素小於當前元素的下標為止,因為高度相等的話只需要統計最左邊的柱子和他的寬度即可,中間的沒必要統計,因為都一樣。 如果棧為空,左邊界為0,否則左邊界為棧頂下標,右邊界為陣列長度
 1 class Solution {
 2     public int largestRectangleArea(int[] heights) {
 3     
 4         Stack<Integer> stack = new Stack<>();
 5         int len = heights.length;
 6         int maxArea = 0;
 7         for(int i = 0; i < len; i++){
 8             // 如果當前高度大於棧頂下標對應的高度,直接入棧,否則迴圈出棧,直至當前高度大於棧頂高度或者棧為空
 9             while(!stack.isEmpty() && heights[i] < heights[stack.peek()]){
10                 int index = stack.pop();   
11                 int width = 0;
12                 // 計算寬度,如果棧為空,左邊界為0,右邊界為i,  否則左邊界為棧頂下標,右邊界為陣列長度
13                 if(stack.isEmpty()){
14                     width = i;
15                 }else{
16                     width = i - stack.peek() - 1;
17                 }
18                 maxArea = Math.max(maxArea, width * heights[index]);
19             }
20             stack.push(i);
21         }
22         // 一次遍歷之後,出棧棧中剩餘元素,
23         while(!stack.isEmpty()){
24             int index = stack.pop();
25             // 出棧過程中如果當前出棧的元素等於棧頂下標對應的元素,
26             // 持續出棧,直到棧頂下標元素小於當前元素的下標為止
27             while(!stack.isEmpty() && heights[stack.peek()] == heights[index]){
28                 stack.pop();
29             }
30             int width = 0;
31             // 如果棧為空,左邊界為0, 否則左邊界為棧頂下標,右邊界為陣列長度
32             if(stack.isEmpty()){
33                 width = len;
34             }else{
35                 width = len - stack.peek() - 1;
36             }
37             maxArea = Math.max(maxArea, width * heights[index]);
38         }
39         return maxArea;
40     }
41 }

leetcode執行用時:12 ms > 71.41%, 記憶體消耗:39.9 MB > 63.66%

複雜度分析:

時間複雜度:O(n)。每個元素下標最多隻被入棧一次以及出棧一次,所以 時間複雜度為O(n)。

空間複雜度:O(n)。空間花費取決於棧的大小,棧的大小最大為O(n-1), 即當heights[]陣列遞增排列時,所有元素的下標都會入隊,所以空間複雜度為O(n)。