单调栈所有模版(2)

矩形单调栈

矩形单调栈模版:

本模版是为了求矩形面积,其中最大的是5和6两个矩形

我们想要这个数组中最大矩形面积组合,我们需要利用单调栈的思想

首先我们需要明白,要求的矩形面积他的高一定是数组中的某一个数字,因为如果高不是数组中高等一个数字,我们可以在不超过任何一个高的前提下增加到数组中的某一个数字。

那么接下来我们要想到如何求最大的矩形面积,如果我们以数组中的第二个数字为高,那么此时,从第二个数字,矩形向两边延伸,发现,没有任何一个高小于1这个高,所以矩形的面积是一直增大的,那么最大的矩形面积就是把整个数组都算上,

接下来我们以5为高,矩形向两边延伸,发现左边的第一个数字就会导致高不是5,所以矩形不向左延伸,向右同理延伸到6,那么此时以5为高的矩阵大小就10.

通过上述简短的分析,我们可以看出,我们要保证某一个元素为高,我们就要保证,矩阵中没有比当前高还小的元素,我们很轻松的就想到了利用单调栈来找到,用,两边第一个小于自己的元素。

接下来给出代码三次遍历模版:

cpp 复制代码
#include <iostream>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int n = heights.size();
        vector<int> left(n, -1);    // 存储每个柱子左边第一个比它小的索引
        stack<int> st;
        
        // 从左向右遍历,计算left数组
        for (int i = 0; i < n; i++) {
            while (!st.empty() && heights[i] <= heights[st.top()]) {
                st.pop();
            }
            if (!st.empty()) {
                left[i] = st.top();
            }
            st.push(i);
        }

        vector<int> right(n, n);     // 存储每个柱子右边第一个比它小的索引
        st = stack<int>();           // 清空栈
        
        // 从右向左遍历,计算right数组
        for (int i = n - 1; i >= 0; i--) {
            while (!st.empty() && heights[i] <= heights[st.top()]) {
                st.pop();
            }
            if (!st.empty()) {
                right[i] = st.top();
            }
            st.push(i);
        }

        // 计算最大矩形面积
        int ans = 0;
        for (int i = 0; i < n; i++) {
            ans = max(ans, heights[i] * (right[i] - left[i] - 1));
        }
        return ans;
    }
};

int main() {
    Solution solution;
    int n;
    
    // 读取柱子数量
    cout << "请输入柱子的数量: ";
    cin >> n;
    
    // 读取柱子高度
    vector<int> heights(n);
    cout << "请输入" << n << "个柱子的高度(用空格分隔): ";
    for (int i = 0; i < n; i++) {
        cin >> heights[i];
    }
    
    // 计算并输出最大矩形面积
    int result = solution.largestRectangleArea(heights);
    cout << "最大矩形面积为: " << result << endl;
    
    return 0;
}

当然三次循环的次数我们肯定是可以优化的,我们可以采用一次遍历的方法,在两个单调栈出栈的时候计算面积大小

cpp 复制代码
#include <iostream>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        heights.push_back(-1);  // 关键优化1:添加哨兵值,确保最终清空栈
        stack<int> st;
        st.push(-1);           // 关键优化2:初始化栈底哨兵
        int ans = 0;
        
        // 单次遍历完成计算(优化3)
        for (int right = 0; right < heights.size(); ++right) {
            // 维护单调递增栈
            while (st.size() > 1 && heights[right] <= heights[st.top()]) {
                int height_idx = st.top();  // 当前处理的柱子索引
                st.pop();
                int left_bound = st.top();  // 左边界来自新的栈顶
                // 计算面积(优化4:即时计算)
                ans = max(ans, heights[height_idx] * (right - left_bound - 1));
            }
            st.push(right);
        }
        
        heights.pop_back();  // 恢复原数组(可选)
        return ans;
    }
};

int main() {
    Solution sol;
    
    // 测试用例1
    vector<int> heights1 = {2,1,5,6,2,3};
    cout << "测试1 [2,1,5,6,2,3] 最大面积: " 
         << sol.largestRectangleArea(heights1) << endl;  // 应输出10
    
    // 测试用例2
    vector<int> heights2 = {2,4};
    cout << "测试2 [2,4] 最大面积: "
         << sol.largestRectangleArea(heights2) << endl;  // 应输出4
    
    // 用户输入模式
    /*
    int n;
    cout << "输入柱子数量: ";
    cin >> n;
    vector<int> input(n);
    cout << "输入" << n << "个高度: ";
    for(int i=0; i<n; ++i) cin >> input[i];
    cout << "最大面积: " << sol.largestRectangleArea(input) << endl;
    */
    
    return 0;
}

典型例题是84. 柱状图中最大的矩形 - 力扣(LeetCode)

本文参考了力扣的灵山爱抚茶的题单分享|【算法题单】单调栈(矩形面积/贡献法/最小字典序)- 讨论 - 力扣(LeetCode)

相关推荐
敲键盘的小夜猫2 分钟前
Retrievers检索器+RAG文档助手项目实战
java·数据库·算法
L_14219068711 分钟前
数据结构之排序
数据结构·算法·排序算法
zyq~18 分钟前
【课堂笔记】标签传播算法Label Propagation Algorithm(LPA)
人工智能·笔记·算法·机器学习·概率论·lpa·半监督学习
白熊18827 分钟前
【机器学习基础】机器学习入门核心算法:多分类与多标签分类算法
算法·机器学习·分类
珂朵莉MM1 小时前
2022 RoboCom 世界机器人开发者大赛(睿抗 caip) -高职组(国赛)解题报告 | 科学家
java·人工智能·python·算法·职场和发展·机器人
STY_fish_20123 小时前
手拆STL
java·c++·算法
小纭在努力3 小时前
【算法设计与分析】实验——改写二分搜索算法,众数问题(算法分析:主要算法思路),有重复元素的排列问题,整数因子分解问题(算法实现:过程,分析,小结)
数据结构·python·学习·算法·算法设计与分析·实验报告·实验
芜湖xin4 小时前
【题解-洛谷】B4278 [蓝桥杯青少年组国赛 2023] 简单算术题
算法·
理智的灰太狼4 小时前
题目 3298: 蓝桥杯2024年第十五届决赛真题-兔子集结
算法·职场和发展·蓝桥杯
kingmax542120087 小时前
【洛谷P9303题解】AC- [CCC 2023 J5] CCC Word Hunt
数据结构·c++·算法·广度优先