代码随想录算法训练营第六十四天_第十章_单调栈 | 84. 柱状图中最大的矩形
创始人
2024-05-23 17:03:33
0

LeetCode 84. 柱状图中最大的矩形

        给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。求在该柱状图中,能够勾勒出来的 矩形的最大面积

视频讲解文章讲解https://programmercarl.com/0084.%E6%9F%B1%E7%8A%B6%E5%9B%BE%E4%B8%AD%E6%9C%80%E5%A4%A7%E7%9A%84%E7%9F%A9%E5%BD%A2.html#%E5%8F%8C%E6%8C%87%E9%92%88%E8%A7%A3%E6%B3%95

  • 思路:
    • 双指针解法:对于每一个i,以heights[i]为矩形的长,找最大宽度,求得面积来更新 result
      • 从 i 出发,向左找第一个高度小于 heights[i] 的柱子,记其下标为 left
      • 从 i 出发,向右找第一个高度小于 heights[i] 的柱子,记其下标为 right
      • 最大宽度(left, right)👉right - left - 1
      • result = max(result, (right - left - 1) * heights[i]);
    • 动态规划解法:两个dp数组
      • 数组 minLeftIndex:记录每个柱子 左边第一个低于该柱子的下标
      • 数组 minRightIndex:记录每个柱子 右边第一个低于该柱子的下标
      • 注意:minLeftIndex vs 接雨水 maxLeft
        1. 左(右)边第一个低于 i 的柱子 vs 左边最高的柱子
        2. 下标 vs 高度
        3. 循环查找 vs 直接由 maxLeft[i - 1] 与 i 高度取大
    • 单调栈解法:
      • 从栈顶到栈底(高度)递减;
      • height[st.top()] == height[i],有两种处理思路:
        • 出栈旧下标,入栈新下标:相当于保留等高柱的最右一个
        • 直接令 i 入栈,栈中柱子高度不是严格单调递减:相当于以等高柱的最左一个计算实际的最大宽度,并更新result
      • 自己:
        • height[st.top()] > height[i]:right = i 
          • 以栈顶柱子高度为矩形的长:int h = height[st.top()];
          • 以栈顶第二个元素下标为 left,矩形的最大宽度(left, i)👉i - left - 1
          • 如果没有栈顶第二个元素,left 为 -1
        • 单独处理栈中剩余元素,height[st.top()] > 0,right = heights.size()
      • 代码随想录:数组首尾分别加入元素0
        左:直接处理原数组                                         右:数组首尾分别加入元素 0
        ​​for循环结束后                                                    for循环结束后
        需单独处理栈中剩余元素                                    所有元素都已经处理完
  • 代码:
// 双指针:
class Solution {
public:int largestRectangleArea(vector& heights) {int sum = 0;for (int i = 0; i < heights.size(); i++) {int left = i;int right = i;for (; left >= 0; left--) {if (heights[left] < heights[i]) break;}for (; right < heights.size(); right++) {if (heights[right] < heights[i]) break;}int w = right - left - 1;int h = heights[i];sum = max(sum, w * h);}return sum;}
};
// 时间复杂度:O(n^2)
// 空间复杂度:O(1)
// 动态规划:
class Solution {
public:int largestRectangleArea(vector& heights) {vector minLeftIndex(heights.size());vector minRightIndex(heights.size());int size = heights.size();// 记录每个柱子 左边第一个小于该柱子的下标minLeftIndex[0] = -1; // 注意这里初始化,防止下面while死循环for (int i = 1; i < size; i++) {int t = i - 1;// 这里不是用if,而是不断向左寻找的过程while (t >= 0 && heights[t] >= heights[i]) t = minLeftIndex[t];minLeftIndex[i] = t;}// 记录每个柱子 右边第一个小于该柱子的下标minRightIndex[size - 1] = size; // 注意这里初始化,防止下面while死循环for (int i = size - 2; i >= 0; i--) {int t = i + 1;// 这里不是用if,而是不断向右寻找的过程while (t < size && heights[t] >= heights[i]) t = minRightIndex[t];minRightIndex[i] = t;}// 求和int result = 0;for (int i = 0; i < size; i++) {int sum = heights[i] * (minRightIndex[i] - minLeftIndex[i] - 1);result = max(sum, result);}return result;}
};
// 单调栈:
// 版本一:从栈顶到栈底严格单调递减
class Solution {
public:int largestRectangleArea(vector& heights) {stack st;heights.insert(heights.begin(), 0); // 数组头部加入元素0heights.push_back(0); // 数组尾部加入元素0st.push(0);int result = 0;// 第一个元素已经入栈,从下标1开始for (int i = 1; i < heights.size(); i++) {// 注意heights[i] 是和heights[st.top()] 比较 ,st.top()是下标if (heights[i] > heights[st.top()]) {st.push(i);} else if (heights[i] == heights[st.top()]) {st.pop(); // 这个可以加,可以不加,效果一样,思路不同st.push(i);} else {while (heights[i] < heights[st.top()]) { // 注意是whileint mid = st.top();st.pop();int left = st.top();int right = i;int w = right - left - 1;int h = heights[mid];result = max(result, w * h);}st.push(i);}}return result;}
};// 精简版:合并情况一、二,从栈顶到栈底非严格单调递减(栈中可以有高度相同的柱子)
class Solution {
public:int largestRectangleArea(vector& heights) {stack st;heights.insert(heights.begin(), 0); // 数组头部加入元素0heights.push_back(0); // 数组尾部加入元素0st.push(0);int result = 0;for (int i = 1; i < heights.size(); i++) {while (heights[i] < heights[st.top()]) {int mid = st.top();st.pop();int w = i - st.top() - 1;int h = heights[mid];result = max(result, w * h);}st.push(i);}return result;}
};

相关内容

热门资讯

【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
AsusVivobook无法开... 首先,我们可以尝试重置BIOS(Basic Input/Output System)来解决这个问题。...
ASM贪吃蛇游戏-解决错误的问... 要解决ASM贪吃蛇游戏中的错误问题,你可以按照以下步骤进行:首先,确定错误的具体表现和问题所在。在贪...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...