[84] leetcodeヒストグラム最大矩形(動的プログラミング、スタック)

トピックへのリンク:https://leetcode-cn.com/problems/largest-rectangle-in-histogram/

タイトル説明

所与のnヒストグラムの各カラムの高さを表す非負整数。互いに隣接する各列、および1の幅。

このヒストグラムを求めるには、最大面積は、長方形を概説することができます。

ここに画像を挿入説明

上記各列の幅は、[2,1,5,6,2,3]の高さと仮定すると、1であることを特徴ヒストグラムの例です。

ここに画像を挿入説明

斜線部は、矩形領域、10個のユニットの面積で概説することができる最大値です。

考え

1つの暴力

i左境界として位置、j横断i~n得る(i,j)最低高さ部と、(j-i+1)*minHeightで得られたi左端点、j右点として矩形の最大面積。

複雑性分析

時間計算: ザ・ n個 2 O(n^2) 我々は右のすべての可能な列を列挙する必要があります。
宇宙の複雑さ: ザ・ 1 O(1) 追加のスペースはありません。

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        if (heights.empty()) return 0;
        int maxArea = 0;
        for (int i = 0; i < heights.size(); ++i) {
            int minHeight = heights[i];
            for (int j = i; j < heights.size() && heights[j]!=0; ++j){
                minHeight = min(minHeight, heights[j]);
                maxArea = max(maxArea,minHeight*(j-i+1));
            }
        }
        return maxArea;
    }
};

残念ながら、残業=。=!
ここに画像を挿入説明

スタック2

この方法では、スタックを維持します。最初に、我々は入れ-1開始を示すために、スタックの最上位に。それは隣接する列減少の関係に遭遇するまで、初期化中、左から右へ順に、我々はスタックにシリアル番号を掲載していきます、それはありますa[i-1] > a[i]a[i−1]>a[i]今、我々はそれが遭遇するまで、ポップ番号をスタックし始めstack[j]会うがa[stack[j]]≤a[i]我々は添字を開くたびに、我々は最大の矩形領域として使用し、高電流素子幅で形成されたポップアップ要素があるstack[top-1]という列の間。我々はポップ場合には、あるstack[top]ため、元の配列インデックス内の現在の要素のレコード、i現在のポップアップ要素は、高い最大の矩形領域です。

(i−stack[top−1]−1)×a[stack[top]]

我々は、配列の最後に到着したときにさらに、我々はすべてのスタックからポップ残りの要素をスタックします。:ポップアップの各要素では、我々は、エリア検索するには、次の式を使用してちょうどでしポップの要素を表します。したがって、私たちは地域によって各矩形矩形領域を最大限に活用することができ、比較的新しい計算です。(stack[top]−stack[top−1])×a[stack[top]]stack[top]

複雑分析
時間の複雑さ: ザ・ n個 O(n) 各nは、それぞれの時間を飛び出るデジタルプッシュがあります。
宇宙の複雑さ: ザ・ n個 O(n) 要素のスタックを格納するために使用されます。

/*
 * 单调栈
 * 时间复杂度O(n) 空间复杂度O(n)
 */
class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        if (heights.empty()) return 0;
        stack<int> s;   // 存储序号
        s.push(-1);
        int maxArea = 0;
        for (int i = 0; i < heights.size(); ++i) {
            // 下降时pop
            while (s.top() != -1 && heights[s.top()] >= heights[i]){
                int tmp = s.top();
                s.pop();
                // 用弹出元素作为高形成的最大面积矩形,其宽是当前元素与s[top-1]之间的那些柱子
                maxArea = max(maxArea, heights[tmp] * (i-s.top() - 1));
            }
            s.push(i);
        }
        while (s.top()!= -1){
            int tmp = s.top();
            s.pop();
            int curArea = heights[tmp] * (heights.size() - s.top() - 1);
            maxArea = max(maxArea, curArea);
        }

        return maxArea;
    }
};

ここに画像を挿入説明

おすすめ

転載: blog.csdn.net/zjwreal/article/details/91477800