LeetCode | C++ 单调栈——84.柱状图中最大的矩形

52 篇文章 0 订阅

84.柱状图中最大的矩形

84题目链接

暴力解法

以每一个柱子为基准,都去找左边比它矮的 右边比它矮的,这样就确定了它的宽,再用这个柱子的高去 乘以 它的 宽,就能算出来 在这个柱状图中,它所能形成的 矩形面积,最后选一个最大的

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        // 暴力解法
        int maxArea = heights[0];
        for (int i = 0; i < heights.size(); i++) {
            int l = -1;
            int r = heights.size();
            for (int j = i - 1; j >= 0; j--) {
                if (heights[j] < heights[i]) {
                    l = j;
                    break;
                }
            }
            for (int j = i + 1; j < heights.size(); j++) {
                if (heights[j] < heights[i]) {
                    r = j;
                    break;
                }
            }
            maxArea = max(maxArea, heights[i] * (r - l - 1));
        }
        return maxArea;
    }
};

双指针优化

定义两个数组 存储每个柱子的 左右比它矮的下标,在遍历的时候,

记录左边比它矮的下标, 从 左到右遍历, 记录的时候利用 之前记录过的值

记录右边比它矮的下标,从 右到左遍历,记录的时候 利用 之前记录过大值。

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        // 双指针解法
        // 需要记录每个柱子 左边 比它小的下标 以及右边比它小的下标
        vector<int> minLeftIndex(heights.size());
        vector<int> minRightIndex(heights.size());

        // 先记录左边,从前往后遍历
        minLeftIndex[0] = -1; // 避免下面出现死循环
        for (int i = 0; i < heights.size(); i++) {
            int l = i - 1;
            while (l >= 0 && heights[l] >= heights[i]) l = minLeftIndex[l];
            minLeftIndex[i] = l;
        }
        // 再记录右边, 从后往前比哪里
        minRightIndex[heights.size() - 1] = heights.size(); // 防止下面出现死循环
        for (int i = heights.size() - 1; i >= 0; i--) {
            int r = i + 1;
            while (r < heights.size() && heights[r] >= heights[i]) r = minRightIndex[r];
            minRightIndex[i] = r;
        }
        // 再计算最大面积
        int maxArea = 0;
        for (int i = 0; i < heights.size(); i++) {
            int w = minRightIndex[i] - minLeftIndex[i] - 1;
            maxArea = max(maxArea, w * heights[i]);
        }
        return maxArea;
    }
};

单调栈

和 42.接雨水 类似,需要注意的是 该题 求得是 比中间柱子矮的, 需要单调递减, 同时首尾需要加上 0;

首 加上 0:以 柱形元素为[8, 6, 4, 2]为例,6 比 8 小,需要弹栈,此时只有 mid 和 right,缺少 left

尾 加上 0:以 柱形元素为[2, 4, 6, 8]为例,将会把所有元素全部入栈,没有计算过程,因此 尾巴加上 0, 进行计算。

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        // 单调栈
        stack<int> st;
        heights.insert(heights.begin(), 0);
        heights.insert(heights.end(), 0);
        int maxArea = 0;
        for (int i = 0; i < heights.size(); i++) {
            while(!st.empty() && heights[i] < heights[st.top()]) {
                int mid = st.top();
                st.pop(); 
                if (!st.empty()) {
                    int r = i;
                    int l = st.top();
                    int w = r - l - 1;
                    maxArea = max(maxArea, w * heights[mid]);
                }
            }
            st.push(i);
        }
        return maxArea;

    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值