力扣第84 题柱状图中最大的矩形 C++ 单调栈 Java

题目

84. 柱状图中最大的矩形

困难

相关标签

数组 单调栈

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。

求在该柱状图中,能够勾勒出来的矩形的最大面积。

示例 1:

复制代码
输入:heights = [2,1,5,6,2,3]
输出:10
解释:最大的矩形为图中红色区域,面积为 10

示例 2:

复制代码
输入: heights = [2,4]
输出: 4

提示:

  • 1 <= heights.length <=105
  • 0 <= heights[i] <= 104

思路和解题方法

  1. int result = 0;:初始化结果变量为0,用来存放最大矩形面积。
  2. stack<int> st;:声明一个整型栈st,用来存放数组元素的下标。
  3. heights.insert(heights.begin(), 0);:在heights数组头部插入一个值为0的元素。
  4. heights.push_back(0);:在heights数组尾部插入一个值为0的元素。
  5. st.push(0);:将0这个下标入栈。

接下来是for循环,遍历heights数组:

  1. for (int i = 1; i < heights.size(); i++):从下标1开始遍历heights数组。
  2. if (heights[i] > heights[st.top()]):如果当前高度大于栈顶元素所对应的高度,则将当前下标入栈。
  3. else if (heights[i] == heights[st.top()]):如果当前高度等于栈顶元素所对应的高度,则不做任何操作。
  4. else:如果当前高度小于栈顶元素所对应的高度,进入循环。
  5. while (!st.empty() && heights[i] < heights[st.top()]):当栈不为空且当前高度小于栈顶元素所对应的高度时,执行循环。
  6. int mid = st.top(); st.pop();:取出栈顶元素的下标,并将其出栈。
  7. if (!st.empty()):如果栈不为空,说明存在左边界。
  8. int left = st.top(); int right = i;:获取左边界和右边界的下标。
  9. int w = right - left - 1; int h = heights[mid];:计算矩形的宽度和高度。
  10. result = max(result, w * h);:更新最大矩形面积。

最后,返回计算得到的最大矩形面积result。

复杂度

时间复杂度:

O(n)

时间复杂度为O(n),其中n是输入数组heights的长度。因为在一次遍历中,每个元素最多被压入和弹出栈各一次,所以总的操作次数与输入数组的长度成线性关系。

空间复杂度

O(n)

空间复杂度为O(n),主要是由栈st所使用的额外空间造成的。

c++ 代码

cpp 复制代码
class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int result = 0; // 初始化最大面积为0
        stack<int> st; // 定义一个栈来辅助计算
        heights.insert(heights.begin(), 0); // 数组头部加入元素0
        heights.push_back(0); // 数组尾部加入元素0
        st.push(0); // 将0入栈作为起始位置

        // 从下标1开始遍历数组
        for (int i = 1; i < heights.size(); i++) {
            if (heights[i] > heights[st.top()]) { // 情况一:当前高度大于栈顶高度,入栈
                st.push(i);
            } else if (heights[i] == heights[st.top()]) { // 情况二:当前高度等于栈顶高度,可以忽略
                st.pop(); // 这个可以加,可以不加,效果一样,思路不同
                st.push(i);
            } else { // 情况三:当前高度小于栈顶高度,需要计算面积并更新最大面积
                while (!st.empty() && heights[i] < heights[st.top()]) { // 注意是while
                    int mid = st.top(); // 弹出栈顶元素作为矩形的高度
                    st.pop();
                    if (!st.empty()) {
                        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; // 返回最大面积
    }
};

简洁代码

cpp 复制代码
class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        stack<int> st; // 创建一个整型栈st,用来存放数组元素的下标
        heights.insert(heights.begin(), 0); // 在heights数组头部插入一个值为0的元素
        heights.push_back(0); // 在heights数组尾部插入一个值为0的元素
        st.push(0); // 将0这个下标入栈
        int result = 0; // 初始化结果变量为0,用来存放最大矩形面积
        for (int i = 1; i < heights.size(); i++) { // 遍历heights数组
            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; // 返回计算得到的最大矩形面积
    }
};

Java代码

java 复制代码
class Solution {
    public int largestRectangleArea(int[] heights) {
        // 创建一个新数组newHeight,长度比原数组heights多2,并在两端补0
        int[] newHeight = new int[heights.length + 2];
        System.arraycopy(heights, 0, newHeight, 1, heights.length); // 复制heights数组到newHeight数组
        newHeight[heights.length+1] = 0; // 在newHeight数组末尾加入一个值为0的元素
        newHeight[0] = 0; // 在newHeight数组头部加入一个值为0的元素

        Stack<Integer> stack = new Stack<>(); // 创建一个整型栈stack,用来存放数组元素的下标
        stack.push(0); // 将0这个下标入栈

        int res = 0; // 初始化结果变量为0,用来存放最大矩形面积
        for (int i = 1; i < newHeight.length; i++) { // 遍历newHeight数组
            while (newHeight[i] < newHeight[stack.peek()]) { // 当当前高度小于栈顶元素所对应的高度时,执行循环
                int mid = stack.pop(); // 取出栈顶元素的下标,并将其出栈
                int w = i - stack.peek() - 1; // 计算矩形的宽度
                int h = newHeight[mid]; // 获取矩形的高度
                res = Math.max(res, w * h); // 更新最大矩形面积
            }
            stack.push(i); // 将当前下标入栈
        }
        return res; // 返回计算得到的最大矩形面积
    }
}

觉得有用的话可以点点赞,支持一下。

如果愿意的话关注一下。会对你有更多的帮助。

每天都会不定时更新哦 >人< 。

相关推荐
以后不吃煲仔饭7 分钟前
Java基础夯实——2.7 线程上下文切换
java·开发语言
进阶的架构师8 分钟前
2024年Java面试题及答案整理(1000+面试题附答案解析)
java·开发语言
The_Ticker13 分钟前
CFD平台如何接入实时行情源
java·大数据·数据库·人工智能·算法·区块链·软件工程
程序猿阿伟14 分钟前
《C++ 实现区块链:区块时间戳的存储与验证机制解析》
开发语言·c++·区块链
大数据编程之光36 分钟前
Flink Standalone集群模式安装部署全攻略
java·大数据·开发语言·面试·flink
Lenyiin1 小时前
02.06、回文链表
数据结构·leetcode·链表
爪哇学长1 小时前
双指针算法详解:原理、应用场景及代码示例
java·数据结构·算法
爱摸鱼的孔乙己1 小时前
【数据结构】链表(leetcode)
c语言·数据结构·c++·链表·csdn
Dola_Pan1 小时前
C语言:数组转换指针的时机
c语言·开发语言·算法
ExiFengs1 小时前
实际项目Java1.8流处理, Optional常见用法
java·开发语言·spring