最大矩形问题

柱状图中最大的矩形

题目

分析

矩形的面积等于宽乘以高,因此只要能确定每个矩形的宽和高,就能计算它的面积。如果直方图中一个矩形从下标为 i 的柱子开始,到下标为 j 的柱子结束,那么这两根柱子之间的矩形(含两端的柱子)的宽是 j-i+1,矩形的高就是两根柱子之间的所有柱子最矮的高度。

暴力解法(不可取)

        如果能逐一找出直方图中所有矩形并比较它们的面积,就能够得到最大矩形的面积。方法为:采用嵌套的二重循环遍历所有矩形,并比较他们的面积。该种方法的时间复杂度为O(N^2),根据题目所给的提示可知,这种方法不能解决本题,会超时。

代码为

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int n=heights.size();
        int maxarea=0;
        for(int i=0;i<n;i++){
            int minheight=heights[i];
            for(int j=i;j<n;j++){
                minheight=min(minheight,heights[j]);
                int area=minheight*(j-i+1);
                maxarea=max(maxarea,area);
            }
        }
        return maxarea;
    }
};
分治法(本题不可取)

        仔细观察直方图可以发现,这个直方图的最大矩形有3中可能:

第一种:矩形通过直方图中最矮的柱子;

第二种:矩形的起始柱子和终止柱子都在直方图中最矮柱子的左侧;

第三种:矩形的起始柱子和终止柱子都在直方图中最矮柱子的右侧。

第二种和第三种从本质上来说和求整个直方图的最大矩形面积是同一个问题,可以用递归函数解决。

代码为:

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        return helper(heights,0,heights.size()-1);
    }

    int helper(vector<int>& heights,int start,int end){
        if(start>end) return 0;
        else if(start==end) return heights[start];
        else{
            int minindex=start;
            for(int i=start+1;i<=end;i++){
                if(heights[i]<heights[minindex])
                    minindex=i;
            }

            int area=(end-start+1)*heights[minindex];
            int left=helper(heights,start,minindex-1);
            int right=helper(heights,minindex+1,end);

            return max(area,max(left,right));
        }
    }
};
单调栈法(可取)

        下面介绍一种非常高效,巧妙的解法。这种解法用一个栈保存直方图的柱子,并且在栈中的柱子的高度是递增排序的。为了方便计算矩阵的高度,栈中保存的是柱子在数组中的下标,可以根据下标得到柱子的高度。

        这种解法的基本思想是确保保存在栈中的直方图的柱子的敢赌是递增排序的。假设从左到右逐一扫描数组中的每根柱子,如果当前柱子的高度大于位于栈顶柱子的高度,那么将该柱子的下标入栈;否则,将位于栈顶的柱子的下标出栈,并且计算以位于栈顶的柱子为顶的最大矩形的面积。【注意:此时出栈须满足:栈不为空并且栈顶柱子的高度大于等于当前柱子的高度】

        以某根柱子为顶的最大矩形,一定是从该柱子向两侧眼神知道遇到比它矮的柱子,这个最大矩形的高是该柱子的高,最大矩形的宽是两侧比它矮的柱子中间的间隔。

        如果当前扫描到的柱子的高小于位于栈顶柱子的高,那么将位于栈顶的柱子的下标出栈,并且计算以位于栈顶的柱子为顶的最大矩形的面积。由于保存在栈中的柱子的高度是递增排序的,因此栈中位于栈顶前面的一根柱子一定比位于栈顶的柱子矮,于是很容易就能找到位于栈顶的柱子两侧比它矮的柱子。

        当计算以当前柱子为顶的最大矩形的面积时,如果栈中没有柱子,那么意味着它左侧的柱子都比它高,因此可以想象在下标为 -1 的位置有一根比它矮的柱子。

        当扫描数组中所以柱子之后,栈中可能仍然剩余一些柱子。因此,需要注意将这些柱子的下标出栈并计算以它们为顶的最大矩形的面积。

        在扫描完数组中所有的柱子之后,当计算以当前柱子为顶的最大矩形的面积时,说明它的右侧没有比它矮的柱子,如果一根柱子的右侧有比它矮的柱子,那么当扫描到右侧较矮柱子的时候他就已经出栈了。因此,可以想象下标为数组长度的位置有一根比它矮的柱子。

        由于已经计算了以每根柱子为顶的最大矩形面积,因此比较这些矩形的面积就能得到脂肪图中的最大矩形面积。

代码为

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int n=heights.size();
        stack<int> st;
        st.push(-1);

        int maxarea=0;
        for(int i=0;i<n;i++){
            while(st.top()!=-1 && heights[st.top()]>=heights[i]){
                int height=heights[st.top()];
                st.pop();
                int width=i-st.top()-1;
                maxarea=max(maxarea,height*width);
            }
            st.push(i);
        }

        while(st.top() != -1){
            int height=heights[st.top()];
            st.pop();
            int width=n-st.top()-1;
            maxarea=max(maxarea,height*width);
        }

        return maxarea;
    }
};
最大矩形

题目

分析

        上一道题是关于最大矩形的,这道题也是关于最大矩形的,他们之间有没有某种联系?如果能从矩阵中找出直方图,那么就能通过计算直方图中的最大矩形面积来计算矩阵中的最大矩形面积。

        直方图是由排列在同一基线上的相邻柱子组成的图形,由于题目要求矩形中只包含数字1,因此将矩阵中上下相邻的值为1的各自看成直方图中的柱子,如果分别以矩阵的每行为基线,就可以得到若干行由数字1的格子组成的直方图。如下图所示:

对应的直方图如下:

说明:(a)以矩阵第一行为基线的直方图;(b)以矩阵第二行为基线的直方图;(c)以矩阵第三行为基线的直方图;(d)以矩阵第四行为基线的资方图。

暴力解法(可取)
class Solution {
public:
    int maximalRectangle(vector<string>& matrix) {
        if(matrix.size()==0 || matrix[0].size()==0) return 0;
        int m=matrix[0].size();
        vector<int> v(m);
        int mxarea=0;
        for(string s:matrix){
            for(int i=0;i<m;i++){
                if(s[i]=='0') v[i]=0;
                else v[i]++;
            }
            mxarea=max(mxarea,maxarea(v));
        }
        return mxarea;
    }

    int maxarea(vector<int>& heights) {
        int n=heights.size();
        int maxarea=0;
        for(int i=0;i<n;i++){
            int minheight=heights[i];
            for(int j=i;j<n;j++){
                minheight=min(minheight,heights[j]);
                int area=minheight*(j-i+1);
                maxarea=max(maxarea,area);
            }
        }
        return maxarea;
    }
};
分治法(可取)
class Solution {
public:
    int maximalRectangle(vector<string>& matrix) {
        if(matrix.size()==0 || matrix[0].size()==0) return 0;
        int m=matrix[0].size();
        vector<int> v(m);
        int mxarea=0;
        for(string s:matrix){
            for(int i=0;i<m;i++){
                if(s[i]=='0') v[i]=0;
                else v[i]++;
            }
            mxarea=max(mxarea,maxarea(v));
        }
        return mxarea;
    }

    int maxarea(vector<int>& heights) {
        return helper(heights,0,heights.size()-1);
    }

    int helper(vector<int>& heights,int start,int end){
        if(start>end) return 0;
        else if(start==end) return heights[start];
        else{
            int minindex=start;
            for(int i=start+1;i<=end;i++){
                if(heights[i]<heights[minindex])
                    minindex=i;
            }

            int area=(end-start+1)*heights[minindex];
            int left=helper(heights,start,minindex-1);
            int right=helper(heights,minindex+1,end);

            return max(area,max(left,right));
        }
    }
};
单调栈法(可取)
class Solution {
public:
    int maximalRectangle(vector<string>& matrix) {
        if(matrix.size()==0 || matrix[0].size()==0) return 0;
        int m=matrix[0].size();
        vector<int> v(m);
        int mxarea=0;
        for(string s:matrix){
            for(int i=0;i<m;i++){
                if(s[i]=='0') v[i]=0;
                else v[i]++;
            }
            mxarea=max(mxarea,maxarea(v));
        }
        return mxarea;
    }

    int maxarea(vector<int> v){
        stack<int> st;
        st.push(-1);
        int area=0;
        for(int i=0;i<v.size();i++){
            while(st.top()!=-1 && v[i]<=v[st.top()]){
                int height=v[st.top()];
                st.pop();
                int width=i-st.top()-1;
                area=max(area,height*width);
            }
            st.push(i);
        }
        while(st.top()!=-1){
            int height=v[st.top()];
            st.pop();
            int width=v.size()-st.top()-1;
            area=max(area,height*width);
        }
        return area;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/688025.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

EE trade:通货膨胀时期投资什么最好

当通货膨胀来袭&#xff0c;货币购买力下降&#xff0c;闲置资金贬值速度加快。为了有效抵御通货膨胀&#xff0c;投资者需要选择能够保值甚至增值的投资工具。以下是几种在通货膨胀环境下较为理想的投资选择&#xff1a; 1. 投资股票 收益性和风险性&#xff1a;股票虽然风险…

访问成员变量(反射)

文章目录 前言一、访问成员变量的方法二、Field类 1.常用方法2.实操展示总结 前言 为了实现随时随地调用某个类的某个成员变量&#xff0c;我们可以通过反射的Field类进行调用。这其中需要我们获取该类的Class对象&#xff0c;再调用Field类的相关方法&#xff0c;实时地灵活地…

时间序列新范式!多尺度+时间序列,刷爆多项SOTA

当我们面对复杂模式和多变周期的应用场景&#xff08;比如金融市场分析&#xff09;时&#xff0c;采用多尺度时间序列来做分析和预测是个更好的选择。 这是因为&#xff1a;传统时序方法通常只用固定时间窗口来提取信息&#xff0c;难以适应不同时间尺度上的模式变化。但多尺…

Ezsql(buuctf加固题)

开启环境 SSH连接 第一个为页面地址WEB服务 or 11# 利用万能密码登录 密码可以随便输入或者不输入 这里就可以判断这个题目是让我们加固这个登录页面 防止sql注入 查看index.php 添加以下代码 $username addslashes($username); $password addslashes($password);…

【C++】STL中List的基本功能的模拟实现

前言&#xff1a;在前面学习了STL中list的使用方法&#xff0c;现在我们就进一步的讲解List的一些基本功能的模拟实现&#xff0c;这一讲博主认为是最近比较难的一个地方&#xff0c;各位一起加油。 &#x1f496; 博主CSDN主页:卫卫卫的个人主页 &#x1f49e; &#x1f449; …

Unity DOTS技术(九) BufferElement动态缓冲区组件

文章目录 一.简介二.例子 一.简介 在之前的学习中我们发现Entity不能挂载相同的组件的. 当我们需要用相同的组件时则可以使用.IBufferElementData接口 动态缓冲区组件来实现 二.例子 1.创建IBufferElementData组件 using Unity.Entities; using UnityEngine; //[GenerateAu…

C语言基础——函数

ʕ • ᴥ • ʔ づ♡ど &#x1f389; 欢迎点赞支持&#x1f389; 个人主页&#xff1a;励志不掉头发的内向程序员&#xff1b; 专栏主页&#xff1a;C语言基础&#xff1b; 文章目录 前言 一、函数的概念 二、库函数 2.1 库函数和头文件 2.2 库函数的使用/…

10.【机器学习】十大算法之一决策树(Decision tree)算法原理讲解

【机器学习】十大算法之一决策树&#xff08;Decision tree&#xff09;算法原理讲解 一摘要二个人简介三什么是决策树四什么是树4.1 二叉树4.1.1 特殊的二叉树&#xff1a;4.1.2 举例说明 五决策树的优缺点5.1 优点5.2 缺点 六算法原理七信息熵八信息增益九信息增益率十基尼指…

2 - 寻找用户推荐人(高频 SQL 50 题基础版)

2.寻找用户推荐人 考点: sql里面的不等于&#xff0c;不包含null -- null 用数字判断筛选不出来 select name from Customer where referee_id !2 OR referee_id IS NULL;

uniapp中使用百度ocr识别引入项目

uniapp中使用百度ocr识别引入项目 官网申请地址 orcAPI文档地址 1.先获取token const getToken () > {uni.request({url: https://aip.baidubce.com/oauth/2.0/token,method: POST,data: {grant_type: client_credentials,client_id: **, apikeyclient_secret: **, skey…

实现开源可商用的 ChatPDF RAG:密集向量检索(R)+上下文学习(AG)

实现 ChatPDF & RAG&#xff1a;密集向量检索&#xff08;R&#xff09;上下文学习&#xff08;AG&#xff09; RAG 是啥&#xff1f;实现 ChatPDF怎么优化 RAG&#xff1f; RAG 是啥&#xff1f; RAG 是检索增强生成的缩写&#xff0c;是一种结合了信息检索技术与语言生成…

刷代码随想录有感(94):划分字母区间(怪!)

题干&#xff1a; 代码&#xff1a; class Solution { public:vector<int> partitionLabels(string s) {int hash[26] {0};for(int i 0; i < s.size(); i) hash[s[i] - a] i;vector<int> res;int left 0;int right 0;for(int i 0; i < s.size(); i){r…

算法2:滑动窗口(下)

文章目录 水果成篮找到字符串中所有字母异位词串联所有单词的子串*最小覆盖子串* 水果成篮 两元素排空操作 窗口中存在元素交错情况&#xff0c;所以出窗口一定要出干净&#xff01;&#xff01;&#xff01; class Solution { public:int totalFruit(vector<int>& …

AI图书推荐:《如何利用ChatGPT在线赚钱》

这本书《如何利用ChatGPT在线赚钱》&#xff08;$100m ChatGPT_ How To Make Money Online With ChatGPT -- Sharp, Biily -- 2023 &#xff09;主要阐述如何利用ChatGPT这一强大的语言模型工具在互联网上创造收入。 以下是各章节内容的概要&#xff1a; **引言** - 介绍了Chat…

机器学习——多层感知机

感知机 缺点&#xff1a;只能处理线性问题&#xff0c;感知机无法解决异或问题 在这里偏置就像线性模型的常数项&#xff0c;加入偏置模型的表达能力增强&#xff0c;而激活函数就像示性函数&#xff0c;可以模拟神经元的兴奋和抑制&#xff0c;当大于等于0就输出1。 多层感…

从军事角度理解“战略与战术”

战略与战术&#xff0c;均源于军事术语。 战略&#xff08;Strategy&#xff09;&#xff0c;源自希腊语词汇“strategos&#xff08;将军&#xff09;”和“strategia&#xff08;军事指挥部&#xff0c;即将军的办公室和技能&#xff09;”。指的是指挥全局性作战规划的谋略…

网络基础_02

1.ARP协议 地址解析协议&#xff08;Address Resolution Protocol&#xff09; 已知对方的三层ip地址&#xff0c;需要二层mac地址 当一台设备&#xff08;请求方&#xff09;需要知道某个 IP 地址对应的 MAC 地址时&#xff0c;会使用 ARP封装一个数据帧。这台设备的网络层以…

[职场] 为什么不能加薪? #学习方法#知识分享#微信

为什么不能加薪&#xff1f; 不能加薪的根本原因&#xff0c;终于被我找到了&#xff01; 朋友们&#xff01;职场这个地方是个很神奇的世界&#xff0c;有些规则并不是你想象的那样。我们都希望能在这个世界里施展自己的才华&#xff0c;获得升职加薪的荣耀。然而&#xff0c…

Blender 学习笔记(二)游标与原点

1. 游标 游标是界面中的红色圆圈&#xff1a; 1.1 移动游标 我们可以通过点击工具栏中的游标按钮&#xff0c;来移动游标&#xff0c;或者通过快捷键 shift右键 移动。若想要重置复游标位置&#xff0c;可以用 shiftc 恢复&#xff0c;或则通过 shifts 点击 游标->世界原…

Python中的Paramiko与FTP文件夹及文件检测技巧

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; Python代码的魅力与实用价值 在当今数字化时代&#xff0c;编程已成为一种不可或缺的技能。Python作为一种简洁、易读且功能强大的编程语言&#xff0c;受到了全球开发者的喜爱。它不仅适用于初学者入门&#xff0c…