1. 程式人生 > 實用技巧 >深入理解 JavaScript 執行上下文和執行棧

深入理解 JavaScript 執行上下文和執行棧

技術標籤:每日一題LeetCode

給定 n 個非負整數,用來表示柱狀圖中各個柱子的高度。每個柱子彼此相鄰,且寬度為 1

求在該柱狀圖中,能夠勾勒出來的矩形的最大面積。

在這裡插入圖片描述

以上是柱狀圖的示例,其中每個柱子的寬度為 1,給定的高度為 [2,1,5,6,2,3]。

在這裡插入圖片描述

圖中陰影部分為所能勾勒出的最大矩形面積,其面積為 10 個單位。

示例:

輸入: [2,1,5,6,2,3]
輸出: 10

解答

首先容易想到的是暴力搜尋,分別以heights[i]為矩形的高,再中心擴充套件求矩形寬,但是最後超時了:

class Solution {
public:
    int largestRectangleArea
(vector<int>& heights) { int result = 0; for(int i = 0; i < heights.size(); i++){ int height = heights[i]; int left = i, right = i; while(left >= 0 && heights[left] >= height){ left--; } while
(right < heights.size() && heights[right] >= height){ right++; } result = max(result, height * (right - left - 1)); } return result; } };

暴力搜尋為O(n^2)複雜度,使用單調棧維護左邊最高柱子的高度,每當遍歷到heights[i]時,同棧頂元素對比,若大於棧頂,則直接入棧,否則依次出棧,此時出棧元素對應於前面暴力搜尋解法的作為矩陣高度的柱子,heights[i]

相當於右邊界,為棧頂柱子右側第一個小於其高度的柱子,出棧後新的棧頂一定時舊棧頂元素左側第一個小於其高度的柱子(在開頭新增一個0,保證永遠存在)相當於左邊界,於是求得矩陣面積。為了避免柱子高度全部為遞增或遞減序列,可以在開頭末尾新增一個0

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
    	// 開頭末尾新增0
        vector<int> temp(heights.size() + 2, 0);
        copy(heights.begin(), heights.end(), temp.begin() + 1);

        int result = 0;
        stack<int> s;
        for(int i = 0; i < temp.size(); i++){
            while(!s.empty() && temp[s.top()] > temp[i]){
                int height = temp[s.top()];
                s.pop();
                int weight = i - s.top() - 1;
                result = max(result, height * weight);
            }
            s.push(i);
        }
        return result;
    }
};