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;
    }
};

 

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