20 力扣热题刷题记录之第84题柱状图中最大的矩形

系列文章目录

力扣刷题记录


前言

每天进步一点点!!

一、背景

在这里插入图片描述

来源:力扣
链接:https://leetcode-cn.com/problems/largest-rectangle-in-histogram/

二、我的思路

我的思路是错误的,但还是写一下。

总体就是一次遍历,计算当前最小的高*长度(元素个数)是否比当前数组元素(其长度为1,高为数组值)的面积大,如果大,说明可以累加这个元素,如果不大,说明这个时候需要更换最小的高为当前元素的值了。

如此荒唐的思维,都没有验证可行性,我就下手敲出来了,结果遇到【1,2,3,4,5】这个数组的时候,给我整蒙了。

附上没有AC的代码,毕竟是我自己想的,只通过了72个用例,总共九十多个。

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        stack<int > my_stack;
        int maxArea=0;
        int minHeight=INT_MAX;
        for (int i=0,j=0;i<heights.size();i++,j++)
        {
            minHeight=min(minHeight,heights[i]);
            int area=max(minHeight*(j+1),heights[i]);
            maxArea=max(maxArea,area);
            if(minHeight*(j+1)<=heights[i])
            {
                minHeight=heights[i];
                j=0;
            }
           
           // my_stack.push(maxArea);
        }
        return maxArea;
    }
};

三、官方的思路

1.单调栈

依据官方的思路,我自己写了代码。

总体思想是,遍历数组的时候,找到当前元素的左边届,同理找到右边界。

这个边界是什么意思呢,表示如果用当前这个元素做高,那么它的长度可以是多少,最后计算面积就是:当前元素值*连续的数组元素长。

举例:如何找到元素值为4的左边界,你就看呀,该元素左侧是不是都>=4,直到符合的那一项,记录它的下标,这个就是他的左边界。办法就是用栈取存元素。判断当前元素是否比栈里面的元素小,小的话,就不停出栈。(为什么是小,因为我栈底元素放的是下标-1,表示最左边。如果当前元素一直小于它左侧的元素,那么它的左边界不就接近最左侧嘛,所以这个时候需要出栈)。右侧同理,不过它的栈底元素可以压入数组长度。

代码如下:

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        stack<int > s;//用栈实现记录       
        vector<int > left;//记录左边界
        vector<int > right(heights.size());//记录右边界
        int maxArea=0;//记录最大面积

        s.push(-1);
        for (int i=0;i<heights.size();i++)
        {    
            while (s.top()>=0&&heights[i]<=heights[s.top()])
            {
                s.pop();
            }
            left.push_back(s.top());//记录左侧边界
            s.push(i);//把当前元素下标压入栈
        }

        //把栈清空
        while (!s.empty()){
            s.pop();
        }

        s.push(heights.size());
        for (int i=heights.size()-1;i>=0;i--)
        {    
            while (s.top()<heights.size()&&heights[i]<=heights[s.top()])
            {
                s.pop();
            }
            right[i]=s.top();//记录右侧边界
            s.push(i);//把当前元素下标压入栈
        }

        //求得面积
        for (int i=0;i<heights.size();i++)
        {
            maxArea=max(maxArea,heights[i]*(right[i]-left[i]-1));
        }
        return maxArea;
    }
};

2.单调栈优化

前面的是左右边界分开求,这里一起求,办法就是,每次出栈的话,说明当前栈顶对应元素的右边界为当前的元素,想一下,如果不是这样,那么为什么要出栈呢?

代码如下;

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        stack<int > s;//用栈实现记录       
        vector<int > left;//记录左边界
        vector<int > right(heights.size(),heights.size());//记录右边界
        int maxArea=0;//记录最大面积

        s.push(-1);
        for (int i=0;i<heights.size();i++)
        {    
            while (s.top()>=0&&heights[i]<=heights[s.top()])
            {
                right[s.top()]=i;//记录右侧边界
                s.pop();
            }
            left.push_back(s.top());//记录左侧边界
            s.push(i);//把当前元素下标压入栈
        }

        //求得面积
        for (int i=0;i<heights.size();i++)
        {
            maxArea=max(maxArea,heights[i]*(right[i]-left[i]-1));
        }
        return maxArea;
    }
};

细节:
1、初始化右边界所有的数组值为数组长度,那是因为最后留在栈里面的,其右边界都是最右边。

2、清空栈的办法可以用:s=stack();而不是用while不停pop

总结

有些题目,它本身就是套路,如果没有好的办法,那么直接看人家是怎么写把,毕竟,我们不是创造这个办法的人,我们只是想要一份不错的工作。

创新就交给那些更具天赋的人吧!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值