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

描述

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

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

 

以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]。

 

图中阴影部分为所能勾勒出的最大矩形面积,其面积为 10 个单位。

 

示例:

输入: [2,1,5,6,2,3]
输出: 10

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/largest-rectangle-in-histogram/

求解

    class Solution {
    public:
        // 暴力解法 两层循环遍历所有矩形可能,超时
        int largestRectangleArea_vio(const vector<int> &heights) {
            if (heights.empty()) {
                return 0;
            }

            int res = 0;
            const int N = heights.size();
            for (int i = 0; i < N; ++i) {
                for (int j = i; j < N; ++j) {
                    int area = (j - i + 1) * (*std::min_element(heights.begin() + i, heights.begin() + j + 1));
                    res = std::max(res, area);
                }
            }
            return res;
        }

        // 以每一个点开始往两边寻找,超时
        /*首先,要想找到第 i 位置最大面积是什么?
        是以i 为中心,向左找第一个小于 heights[i] 的位置 left_i;向右找第一个小于于 heights[i] 的位置 right_i
        即最大面积为 heights[i] * (right_i - left_i -1)*/
        int largestRectangleArea_every(const vector<int> &heights) {
            if (heights.empty()) {
                return 0;
            }

            int res = 0;
            const int N = heights.size();
            for (int i = 0; i < N; ++i) {
                // 寻找左边界点
                int left = i - 1;
                while (left >= 0 && heights[left] >= heights[i]) {
                    --left;
                }
                // 寻找右边界点
                int right = i + 1;
                while (right < N && heights[right] >= heights[i]) {
                    ++right;
                }
                res = std::max(res, heights[i] * (right - left - 1));
            }
            return res;
        }

        // 单调栈的思路
        int largestRectangleArea(vector<int> &heights) {
            if (heights.empty()) {
                return 0;
            }
            vector<int> h(heights.size() + 2, 0);
            // h为heights收尾各加上一个0,即[0, heights[0], heights[1], ..., heights[n-1], 0]
            std::copy(heights.cbegin(), heights.cend(), h.begin() + 1);

            const int N = h.size();
            int res = 0;
            vector<int> rec;
            for (int i = 0; i < N; ++i) {
                while (!rec.empty() && h[rec.back()] > h[i]) {
                    int cur = rec.back();
                    rec.pop_back();
                    int left = rec.back() + 1;
                    int right = i - 1;
                    res = std::max(res, (right - left + 1) * h[cur]);
                }
                rec.push_back(i);
            }
            return res;
        }
    };

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值