LeetCode_直方图最大面积(Largest Rectangle in Histogram)

LeetCode: Largest Rectangle in Histogram(直方图最大面积) 具体的题目描述为: Given n non-negative integers representing the histogram's bar height where the width of each bar is 1, find the area of largest rectangle in the histogram. Above is a histogram wher 阅读详情

一、题目

Given n non-negative integers representing the histogram’s bar height where the width of each bar is 1, find the area of largest rectangle in the histogram.

Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3].

The largest rectangle is shown in the shaded area, which has area = 10 unit.

For example,Given height = [2,1,5,6,2,3],return 10.

1.1.1

LeetCode 84题:Largest Rectangle in Histogram,给定一个直方图(下图a),求直方图中能够组成的所有矩形中,面积最大为多少。对于图a来说,我们很容易看出来面积最大的矩形为高度为5和6的直方图组成的矩形(图b隐形部分),其面积为5 * 2 = 10。


二、解题

1.感想

如果就对于图片的示例而言,许多人一看就知道答案了,压根就不需要太多的思考,可是正是因为这种定性的思考,让我们慢慢没法“知其所以然”,也让我们慢慢失去了举一反三的思考方式,就图片的示例而言,之所以我们一看就能看出答案,是因为示例的例子数据太少了,如果数据很多的时候我们能一看就看出答案吗?所以无论面对什么样的题目,我们都不能放弃“知其所以然”,从根本解决问题。

2.暴力搜索

这道题目一个显而易见的解决方法就是暴力搜索:找出所有可能的矩形,然后求出面积最大的那个。要找出所有可能的矩形,只需要从左到右扫描每个立柱,然后以这个立柱为矩形的左边界(假设为第i个),再向右扫面,分别以(i+1, i+2, n)为右边界确定矩形的形状。

这符合我们本能的思考过程:要找出最大的一个,就先列出所有的可能,比较大小后求出最大的那个。然而不幸的是,本能的思考过程通常是简单粗暴而又低效的,就这个题目来说,时间复杂度为N^2 。

3.使用动态规划

用left[i]表示第i个柱子可以最多向左延伸至第left[i]个柱子,形成一个矩形,right[i]则表示向右延伸。遍历两次,分别计算出这两个数组。

再遍历一次,即可求出所有的柱子可以形成的最大的矩形面积。为了减少边界的判断,可以使用哨兵,在两端添加两个柱子高度都为-1.

public class LargestRectangle {

    public static void main(String[] args) {
        int height[] = { 2, 1, 5, 6, 2, 3 };
        int ans = getMaxRectangle(height);
        // lift[]=[0,1,1,3,4,3,6] right[]=[0,1,6,4,4,6,6]
        System.out.println("最大的面积位:" + ans);
    }

    /**
     * 遍历每个柱子可以组成的最大面积
     * 
     * @param heights
     * @return 最大的面积
     */
    public static int getMaxRectangle(int heights[]) {
        int ans = 0;
        int n = heights.length;
        int left[] = new int[n + 1];
        int right[] = new int[n + 1];
        processLR(heights, left, right);
        for (int i = 1; i <= n; i++) {
            int tmp = (right[i] - left[i] + 1) * heights[i - 1];
            if (ans < tmp)
                ans = tmp;
        }
        return ans;
    }

    /**
     * 初始化左右两个数组
     * 
     * @param heights
     * @param left
     * @param right
     */
    public static void processLR(int heights[], int left[], int right[]) {
        int n = heights.length;
        // 用临时数组,设置两个哨兵
        int tempArr[] = new int[n + 2];
        tempArr[0] = -1;
        for (int i = 1; i <= n; i++)
            tempArr[i] = heights[i - 1];
        tempArr[tempArr.length - 1] = -1;

        // 用left[i]表示第i个柱子可以最多向左延伸至第left[i]个柱子
        for (int i = 1; i <= n; i++) {
            int k = i;
            while (tempArr[i] <= tempArr[k - 1])
                k = left[k - 1];
            left[i] = k;
        }

        // 用right[i]表示第i个柱子可以最多向右延伸至第right[i]个柱子
        for (int i = n; i > 0; i--) {
            int k = i;
            while (tempArr[i] <= tempArr[k + 1])
                k = right[k + 1];
            right[i] = k;
        }
    }
}

运行的结果:

2.3.1

4.巧妙使用栈

在网上发现另外一个使用一个栈的O(n)解法,代码非常简洁,栈内存储的是高度递增的下标。对于每一个直方图高度,分两种情况。1:当栈空或者当前高度大于栈顶下标所指示的高度时,当前下标入栈。否则,2:当前栈顶出栈,并且用这个下标所指示的高度计算面积。而这个方法为什么只需要一个栈呢?因为当第二种情况时,for循环的循环下标回退,也就让下一次for循环比较当前高度与新的栈顶下标所指示的高度,注意此时的栈顶已经改变由于之前的出栈。

public class largestRectangleArea {

    public static void main(String[] args) {
        int height[] = { 2, 1, 5, 6, 2, 3 };
        int ans = largestRectangleArea(height);
        System.out.println("最大的面积位:" + ans);
    }

    // O(n) using one stack
    public static int largestRectangleArea(int[] height) {
        // Start typing your Java solution below
        // DO NOT write main() function
        int area = 0;
        java.util.Stack<Integer> stack = new java.util.Stack<Integer>();
        for (int i = 0; i < height.length; i++) {
            if (stack.empty() || height[stack.peek()] < height[i]) {
                stack.push(i);
            } else {
                int start = stack.pop();
                int width = stack.empty() ? i : i - stack.peek() - 1;
                area = Math.max(area, height[start] * width);
                i--;
            }
        }
        while (!stack.empty()) {
            int start = stack.pop();
            int width = stack.empty() ? height.length : height.length
                    - stack.peek() - 1;
            area = Math.max(area, height[start] * width);
        }
        return area;
    }
}

这是看到别人的推演过程,之前看到,就添加到笔记了,没有原著的地址,所以没法标明出处:

一个思维历程

那么这个算法真的就是我等凡夫俗子不能想出来的?难道我们只能仰望高山,恨自己智商不高?我还真不服气呢,于是又静下心去思考这个问题。

这次我们不从已知条件推结果,而直接从结论入手,就是说假设现在已经找到了面积最大的那个矩形。接着我们来分析该矩形有什么特征,然后可以用下面两种方法之一来缩减问题的规模(因为这两种方法都不用找出所有的矩形一一比较)。

找出满足这些特征的矩形,面积最大的矩形肯定是其中之一;
排除那些不满足这些特征的矩形,面积最大的矩形在剩下的那些矩形里面。
为了使考虑情况尽可能全面,画了许多直方图,防止使用原题目图片可能存在的一些特定假设,其中一个直方图如下图:

2.4.1

题目情况分析

通过不断地对多个直方图的观察,发现面积最大的那个矩形好像都包含至少一个完整的bar,那么这条规律适用于所有的直方图吗?我们用反证法来证明,假设某个最大矩形中每个竖直块都是所在的bar的一小段,那么这个矩形高度增加1后仍然是一个合法的矩形,但新的矩形面积更大,与假设矛盾,所以面积最大的矩形必须至少有一个竖直块是整个bar。

至此我们找到了面积最大矩形的一个特性:各组成竖直块中至少有一个是完整的Bar。有了这条特性,我们再找面积最大的矩形时,就有了一个比较小的范围。具体来说就是针对每个bar,我们找出包含这个bar的面积最大的矩形,然后只需要比较这N个矩形即可(N为bar的个数)。

那么问题又来了,如何找出“包含某个bar的面积最大的矩形呢”?对于上面的直方图,包含下标为4的bar的最大矩形如下图橘黄色部分:

2.4.2

局部最大矩形

简单观察一下,就会发现要找到包含某个bar的最大矩形其实很简答,只需要找到高度小于该bar的左、右边界即可,上图中分别是下标为1的bar和下标为10的bar。

至此问题已经变为“对于给定的bar,如何确定高度比它小的左、右边界”。其实求左边界和右边界是同样的求法,下面我们考虑求每个bar的左边界。最直接的思路是对于每个bar,扫面其前面所有的bar,找出最后一个高度小于它的bar,这样的话时间复杂度明显又是N^2 ,Holy Shit。

到这里似乎没有路可走了,但如果我们继续绞尽脑汁地去想,可能(或许你对栈理解的很深入,或许是你在一个类似的问题中用到了栈,当然你也可能想到动态规划的思想,那也是可行的)会联想到栈这一数据结构。用栈维护一个高度递增的bar的集合,也就是说栈底到栈顶部对应的bar的高度越来越大。那么对应一个刚读入的bar,我们只需要比较它的高度和栈顶对应bar的高度,如果当前bar比较高,则弹出栈顶元素继续比较,直到栈顶bar比它低或者栈为空。之后,将当前bar入栈,更新栈内的递增序列。

我们从左到右扫一遍得到每个bar对应的左边界,然后从右到左扫一遍得到bar的右边界。两次扫描过程中,每个bar都只有出栈、入栈操作,所以时间复杂度为O(N)。通过这样的预处理,即可以O(N)的时间复杂度得到每个bar的左右边界。之后对于每个bar求出包含它的最大面积,也即是由左右边界和bar的高度围起来的矩形的面积。再做N次比较,即可得出最终的结果。

这里先预处理用两个栈扫描两次得到左、右边界,再计算面积,是按照推导过程一步一步来的。当我们写完程序后,再综合看这个问题,可能会发现其实没必要这样分开来做,我们可以在扫描的同时,维护一个递增的栈,同时在“合适的”时候计算面积,然后更新最大面积。具体实现方法就是前面给出的那个神奇的算法,不过现在看来一点也不神奇了,我们已经探索到了它背后的思维历程。

当然,条条道路通罗马,上面思维过程只是其中一条通往解决方案的路径,你可能以另一种思维过程找到了答案。不过,我们上面的整个推导过程没有涉及一些类似“神谕”的启发,只是一些简单的方法:比如从结论推导、反证法、归纳总结、联想(可能联想到栈有点难)等,因此每个人都可以学会,并且很容易被大脑记住。值得注意的是,我们的整个思考过程并不简简单单地跟上面写的那样是线性的,它更可能是树形的,只是我们剪去了那些后来证明行不通的枝。

Demo:http://download.youkuaiyun.com/detail/two_water/9670562


三、思考

最后奉上看到别人写的东西,略有感想,故分享。

3.1.1

游戏战斗系统架构设计的演绎之路——从一坨意大利面条到一座精密钟表 摘要:游戏战斗系统架构设计的演进之路 本文系统梳理了游戏战斗系统从早期街机到现代3A大作的架构发展历程。70-80年代的街机游戏采用基础碰撞盒判定(如《街头霸王》);90年代实现动画融合与状态机架构(《最终幻想》《拳皇》);2000年后MMO引入服务器验证与同步技术(《魔兽世界》);3D时代融合物理引擎与智能AI(《GTA5》《只狼》);移动端则发展出轻量化架构与云端判定(《王者荣耀》)。现代战斗系统已实现模块化、数据驱动和热更新,未来趋势是AI裁判与云战斗系统。这一演进过程展现了技术与创意的完美结合,数百 阅读详情

相关推荐

金融领域强化学习在多资产类别动态交易执行中的应用

在金融市场中,多资产类别的交易执行面临着诸多挑战,如市场的不确定性、资产间的复杂相关性等。传统的交易策略往往难以适应动态变化的市场环境。本研究的目的在于探索如何运用强化学习技术,实现多资产类别在动态市场环境下的高效交易执行。具体范围涵盖了从强化学习的基本原理到在多资产交易场景中的实际应用,包括核心算法的实现、数学模型的构建以及项目实战等方面。本文首先介绍研究背景,包括目的、预期读者和文档结构。接着阐述核心概念,包括强化学习和多资产类别动态交易执行的原理及其联系。

AI 领航者的博客 630

直方图之回顾

频数直方图:高度代表频数密度(频数/组距),此时组距为1,则面积代表频数频率直方图:高度代表频率密度(频率/组距),面积代表频率!!

m0_51984816的博客 3366

两层板如何做阻抗控制呢

两层板如何做阻抗控制呢? 这个问题可能很多人都会碰到,有的人在此等需要做阻抗控制的情况都选择做多层板。诚然,多层板在阻抗控制,EMC等等方面都有着天然的优势。然而,在价格上和周期上,两层板就有着绝对优势了。 对于成本非常敏感而又不是太复杂的产品,尽管对于我们硬件工程师而言,有一堆的理由要求使用多层板。然而在面对毛都不懂的老板“别人能做,你为什么不能做?”这个问题时只得低下我们高傲的头颅。 好...

weixin_42005993的博客 2万+

直方图 (Histogram)

用矩形的面积来表示频数分布的图形 在直角坐标中,用横轴表示数据分组,纵轴表示频数密度,各组与相应的频数就形成了一个矩形,即直方图 直方图下的总面积等于总频数(或1) 适用于定距变量 ...

6285

Java:使用Java调用打印机进行打印(JPG、PDF和Word三种文件格式)

目录 一、Java的打印简介 二、Java打印实现 2.1 JPG图片文件格式打印实现 2.2 PDF文件格式打印实现 2.3 Word文件格式打印实现 2.3.1 Word文件采用jacob插件进行打印实现。 2.3.2 先将word转化为pdf文件,然后打印pdf(lz使用) 三、总结 一、Java的打印简介 在我们的实际工作中,经常需要实现打印功能。但由于历史原因,Jav...

vatxiongxiaohui的专栏 8万+

使用Simulink设计并实现一个可调谐的二阶IIR陷波滤波器,实时去除音频中的工频噪声

《基于Simulink的音频陷波滤波器设计与实现》摘要:本文详细介绍了使用Simulink设计陷波滤波器去除音频工频噪声(如50Hz)的方法。核心内容包括:1)二阶IIR陷波滤波器的原理与传递函数;2)Simulink实现步骤(音频系统搭建、滤波器设计、频率跟踪);3)性能分析(频谱对比、时域波形、听觉测试)。通过精准消除特定频率干扰,同时保留语音信号(200Hz-4kHz),有效提升信噪比(>20dB)。文章还探讨了多陷波级联、自适应算法等高级技巧,为音频处理、语音通信等应用提供实用解决方案。

amy_mhd的博客 154

leetcode_question_85 Largest Rectangle in Histogram

Given n non-negative integers representing the histogram's bar height where the width of each bar is 1, find the area of largest rectangle in the histogram. Above is a histogram where width

ZkvIA的博客 1万+

无人机视角下基于YOLOv5/v8/v10的车辆检测系统:从算法原理到UI界面实战

随着无人机技术的普及和智慧城市的发展,无人机视角下的车辆检测在交通监控、战场侦察、灾害救援等领域展现出巨大的应用价值。然而,无人机航拍图像存在目标尺度小、视角多变、背景复杂等挑战。本文深入探讨了如何利用YOLOv5、YOLOv8、YOLOv10三个代表性目标检测算法,构建一套完整的无人机车辆检测系统。文章不仅详细解析了各版本YOLO的核心技术演进,还提供了从数据集准备、模型训练、性能评估到基于PyQt5/PySide6的图形界面开发的完整代码实现。通过本文,读者将能够掌握构建无人机实时车辆检测系统的全流程技

YOLO 172

描述性统计分析 | 直方图

直方图的详细讲解

weixin_42444823的博客 2774

PLC为西门子的S7-1200,舵机为 DS3218,PLC控制舵机旋转程序实现?

🏆 本文收录于《全栈Bug调优(实战版)》专栏,致力于分享我在项目实战过程中遇到的各类Bug及其原因,并提供切实有效的解决方案。无论你是初学者还是经验丰富的开发者,本文将为你指引出一条更高效的Bug修复之路,助你早日登顶,迈向财富自由的梦想🚀!同时,欢迎大家关注、收藏、订阅本专栏,更多精彩内容正在持续更新中。让我们一起进步,Up!Up!Up!    备注: 部分问题/难题源自互联网,经过精心筛选和整理,结合数位十多年大厂实战经验资深大佬经验总结所得,数条可行方案供所需之人参考。

**My Coding Family** 998

【AI Agent 记忆共享实战】【下篇】多 Agent 会话 Session 统一共享实战:全链路工程落地、采集归一、MCP 服务、私有化部署、源码级实战

中篇我们已经锁定最终最优架构方案: 非侵入式、外部旁路采集、只读归一、中心化存储、MCP 按需检索注入。摒弃「改 Agent 源码」「软链接互通」「原生 Session 互导」等不现实方案。本篇直接落地可上线、可简历复用、可个人私有化部署多 Agent 异构 Session专属采集器(Claude/CODex/DSH/OpenCode/Kimi/WorkBuddy/ 豆包)统一消息归一化解析层(解决所有 Schema 异构)增量同步、去重、时间戳对齐核心逻辑。

十年老程序猿,AI 疯狂研究专家,前沿硬核知识分享 481

LeetCode:Largest Rectangle in Histogram(直方图中最大矩形面积)

84. Largest Rectangle in Histogram Given n non-negative integers representing the histogram's bar height where the width of each bar is 1, find the area of largest rectangle in the histogram.   Ab...

但行好事,莫问前程 957

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

[LeetCode]—Largest Rectangle in Histogram 求直方图最大填充矩形面积

Largest Rectangle in Histogram

清水 977

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

LeetCode(084)-Largest Rectangle in Histogram(直方图最大矩形面积)

题目: Given n non-negative integers representing the histogram’s bar height where the width of each bar is 1, find the area of largest rectangle in the histogram. Above is a histogram where width of ea...

Fly_Fly_Zhang的博客 691

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

LeetCode 84. Largest Rectangle in Histogram(直方图中最大矩形面积)

题目描述:    Given n non-negative integers representing the histogram's bar height where the width of each bar is 1, find the area of largest rectangle in the histogram.        Above is a histogram where ...

andersonxie的博客 2800

Largest Rectangle in Histogram (直方图中最大面积) 【leetcode】

题目: Given n non-negative integers representing the histogram's bar height where the width of each bar is 1, find the area of largest rectangle in the histogram. Above is a histogram wh

Havenoidea 的专栏 7296

LeetCode | Largest Rectangle in Histogram(直方图围城的最大矩形面积)

Given n non-negative integers representing the histogram's bar height where the width of each bar is 1, find the area of largest rectangle in the histogram. Above is a histogram where width o

solar一抹阳光的专栏 1137

【LeetCode】84. Largest Rectangle in Histogram——直方图最大面积

Given n non-negative integers representing the histogram's bar height where the width of each bar is 1, find the area of largest rectangle in the histogram. Above is a histogram where width of each b...

weixin_33973600的博客 82

4.1.3LeetCode: Largest Rectangle in Histogram(直方图最大面积)

http://www.cnblogs.com/avril/archive/2013/08/24/3278873.html 具体的题目描述为:   Given n non-negative integers representing the histogram's bar height where the width of each bar is 1, find the are

ZhikangFu的专栏 690

【leetcode每日刷题】Largest Rectangle in Histogram

https://leetcode.com/problems/largest-rectangle-in-histogram/ 求直方图中的最大矩形 从左到右找到最高的矩形,然后从右向左计算最大的面积。 class Solution(object): def largestRectangleArea(self, heights): """ :type h...

菜菜鸟的博客 173

leetcode栈--2、largest-rectangle-in-histogram(直方图最大面积)

题目描述 Givennnon-negative integers representing the histogram's bar height where the width of each bar is 1, find the area of largest rectangle in the histogram. Above is a histogram where wi...

weixin_30820077的博客 115

最大矩形(Stack,Vector,Queue,Deque)

Largest Rectangle in Histogram:https://leetcode.com/problems/largest-rectangle-in-histogram/description/public int largestRectangleArea(int[] height) { int len = height.length; Stack&l...

heiheibupt的博客 215

Leetcode -- Maximal Rectangle

https://oj.leetcode.com/problems/maximal-rectangle/ Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing all ones and return its area  public int maximalRectan

chaochen1407的专栏 387

算法设计与分析第一周练习

题目 Given n non-negative integers a1, a2, …, an , where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find t...

Vilin的博客 281

Leetcode. Largest Rectangle in Histogram

1. 题解 题目 链接🔗:84. Largest Rectangle in Histogram 这道题和42. Trapping Rain Water有些相像,但是42题求的是能围住的最大面积,而本题求的是连成的矩阵的最大面积,因而在计算面积的方法上有些许不同。85. Maximal Rectangle就是在本题基础上的变式,通过一系列变化可以使用本题方法。 分析 简单分析可以知道最大矩形面积有两种情况: 当前矩形的高度heights[i] * 1 当前矩形的高度heights[i] * (向右第一个比

三明治文鱼的博客 7797
上一篇: 微信小程序学习(6)_配置详解
下一篇: Android 网络框架_常用的网络框架
Two_Water
博客等级 码龄12年 573粉丝 134原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值