Leetcode84——柱狀圖中最大的矩形

題目描述:

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

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

方法一:暴力解法O(N^2)複雜度,超時,僅提供思路(踩坑)

直接枚舉每一段,找最小。

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

方法二:分治的思路,每次將區間分爲,最小值,最小值的左半部分,最小值的右半部分。

最大值爲,當前區間長度乘以最小值,左半部分最大值,右半部分最大值三者中的最大值。找最小值部分直接枚舉查找的情況,針對排好序的數組時間複雜度退化爲O(n^2),依舊超時哦,測試用例[1,1,...,1,1]

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int len=heights.size();
        int max_area=calculateMaxArea(0,len-1,heights);
        return max_area;
    }
    int calculateMaxArea(int left,int right,vector<int>& heights)
    {
        if(left>right)return 0;
        int min_current_pos=left;
        for(int i=left+1;i<=right;i++)
            if(heights[min_current_pos]>heights[i])min_current_pos=i;
        int max_left=calculateMaxArea(left,min_current_pos-1,heights);
        int max_right=calculateMaxArea(min_current_pos+1,right,heights);
        int max_area_include_min_value=(right-left+1)*heights[min_current_pos];
        return max(max_area_include_min_value,max(max_left,max_right));
    }

};

方法三:分治法+線段樹維護查詢,時間複雜度將爲O(n*logn)。不超時,可以通過。

class Solution {
struct node
{
    int start_index;
    int end_index;
    int min_index;
    node *left;
    node *right;
};
public:
    int largestRectangleArea(vector<int>& heights) {
        int len=heights.size();
        node* root=buildSegmentTree(0,len-1,heights);
        int max_area=calculateMaxArea(0,len-1,heights,root);
        return max_area;
    }
    int calculateMaxArea(int left,int right,vector<int>& heights,node* root)
    {
        if(left>right)return 0;
        int min_current_pos;
        min_current_pos=querySegmentTree(left,right,heights,root);
        int max_left=calculateMaxArea(left,min_current_pos-1,heights,root);
        int max_right=calculateMaxArea(min_current_pos+1,right,heights,root);
        int max_area_include_min_value=(right-left+1)*heights[min_current_pos];
        return max(max_area_include_min_value,max(max_left,max_right));
    }
    node* buildSegmentTree(int left,int right,vector<int>& heights)
    {
        if(left>right)
        {
            return nullptr;
        }
        node *p=new node();
        p->start_index=left;
        p->end_index=right;
        if(left==right)
        {
            p->left=p->right=nullptr;
            p->min_index=left;
            return p;
        }
        int mid=(left+right)/2;
        p->left=buildSegmentTree(left,mid,heights);
        p->right=buildSegmentTree(mid+1,right,heights);
        p->start_index=left;
        p->end_index=right;
        p->min_index=heights[p->left->min_index]<heights[p->right->min_index]?p->left->min_index:p->right->min_index;
        return p;
    }
     int querySegmentTree(int left,int right,vector<int>&heights,node* root)
     {
         if(left<=root->start_index&&right>=root->end_index)
         {
            return root->min_index;
         }
        int mid=(root->start_index+root->end_index)/2;
        int min_left_index=-1;
        int min_right_index=-1;
        if(mid>=left)
        {
            min_left_index=querySegmentTree(left,right,heights,root->left);
        }
        if(mid+1<=right)
        {
            min_right_index=querySegmentTree(left,right,heights,root->right);
        }
        if(min_left_index!=-1&&min_right_index!=-1)
            return heights[min_left_index]<heights[min_right_index]?min_left_index:min_right_index;
        else if(min_left_index!=-1)return min_left_index;
        else return min_right_index;
     }

};

方法四:棧的方法。最開始把-1加入棧頂。當a[i-1]<=a[i]時,將a[i]加入到棧中。當a[i-1]>a[i]時,將a[top](top=i-1,i-2...)依次彈出,直到a[stack[j]]<=a[i],此時以彈出元素的爲矩形高度的最大面積爲,(i-stack[top-1]-1)*a[stack[top]]。然後將a[i]加入到棧中。當到達數組尾部時,將棧頂元素依次彈出,此時以棧頂元素爲矩形高度的最大面積爲(height.length-stack[top-1]-1)*a[stack[top]]。可以通過比較新矩形的面積來維護最大面積。時間複雜度將爲O(n)。不超時,可以通過。

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int len=heights.size();
        stack<int>index_stack;
        index_stack.push(-1);
        int max_area=0;
        for(int i=0;i<len;i++)
        {
            while(index_stack.top()!=-1&&heights[index_stack.top()]>heights[i])
            {
                int index_top=index_stack.top();
                index_stack.pop();
                max_area=max(max_area,heights[index_top]*(i-index_stack.top()-1));
            }
            index_stack.push(i);
        }
        while(index_stack.top()!=-1)
        {
            int index_top=index_stack.top();
            index_stack.pop();
            max_area=max(max_area,heights[index_top]*(len-index_stack.top()-1));
        }
        return max_area;
    }
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章