• 139、★LeetCode-柱状图中最大的矩形


    题目:

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

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

    示例 1:

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

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

    思路:

    单调栈:在一维数组中,遇到找两侧最值的问题,经常就是单调栈的问题;

    需要考虑栈中存储数值还是下标!

    接雨水和本题虽然没有直接指出找最值,但是通过分析,还是找最值问题,可以使用单调栈解决问题:

    接雨水:按列计算,往两侧找最大值;

    本题:往两侧找第一个小于当前值的值!按照栈底到栈顶递增:出现小于栈顶元素的情况时,就是右侧小于当前值的第一个值出现;栈中一直保持递增(相等的问题不好处理,但是更靠近栈底的数字就包含了所有情况),前一个元素就是左侧第一个!

    1)暴力:for中套while,往两侧找,时间复杂度大

    2)单调栈:本题中会出现:最后栈中保持递增,有许多位置无法处理的情况!对数组扩容,两则加上不改变体积的数值0即可!

    注意坐标的考虑,栈中紧挨着,不代表数组中紧挨着!

    3)动态规划:类似接雨水;时间复杂度还要更好一点

    记录每个位置上,左边和右边第一个小于其值的下标

    代码:

    1)暴力解法:时间复杂度O(N^2),无法通过

    1. class Solution {
    2. public int largestRectangleArea(int[] heights) {
    3. //本题是找矩形:因此只有一个矩形,且需要一个高;每个位置都能充当一个高!只招一种情况
    4. //接雨水:将每个列都当作一次底座!将所有列的雨水情况找到,相加就是结果!
    5. int l = heights.length;
    6. int res = 0;
    7. //分别往最左和最右找最后一个大于等于的下标!
    8. //接雨水,是往左和往右,找第一个大于!
    9. for(int i = 0;i < l;i++){
    10. int left = i;//从当前位置开始,往左找
    11. while(left >= 0 && heights[left] >= heights[i]){
    12. left--;
    13. }
    14. int right = i;//从当前位置开始,往右找
    15. while(right < l && heights[right] >= heights[i]){//找最后一个大于等于的下标
    16. right++;
    17. }
    18. int sum = (right - left - 1) * heights[i];
    19. res = Math.max(res,sum);
    20. }
    21. return res;
    22. }
    23. }

    2)单调栈:

    1. class Solution {
    2. public int largestRectangleArea(int[] heights) {
    3. //单调栈:之前说明,是往左往右找第一个小于其值的位置;
    4. //只用使用单调栈记录顺序即可,就能够o1找到
    5. //这道题的单调栈刚好和接雨水相反!
    6. int res = 0;
    7. //正常处理单调栈,会存在最后栈中保留了递增的元素,有一些情况无法处理
    8. //将数组两端扩容,存放两个不会改变体积的 0;
    9. int [] newHeights = new int[heights.length + 2];
    10. newHeights[0] = 0;
    11. newHeights[newHeights.length - 1] = 0;
    12. for (int index = 0; index < heights.length; index++){
    13. newHeights[index + 1] = heights[index];
    14. }
    15. heights = newHeights;
    16. int l = heights.length;
    17. Deque stack = new LinkedList<>();
    18. //整体的思想还是,找到每一列,以每一列为高,计算其构成的矩形
    19. for(int i = 0;i < l;i++){
    20. while(!stack.isEmpty() && heights[i] < heights[stack.peek()]){
    21. //此时需要处理栈中的情况了:从栈底到栈顶是递增的,因为后面要入栈的都是其右边,碰见小于的前面的就需要处理了
    22. int h = stack.pop();//表示高
    23. int num = heights[h] * (i - stack.peek() - 1);
    24. //当前要入栈的节点处,才是问题的关键;只有当他比栈内余下的元素都大时,才能入栈!
    25. //只要他比栈内的元素小,就需要按顺序处理栈内的元素!
    26. res = Math.max(res,num);
    27. }
    28. //相等时,入不入栈都可以,入栈就是多计算!
    29. stack.push(i);//每个位置都要处理
    30. }
    31. return res;
    32. }
    33. }

    3)动态规划

    1. class Solution {
    2. public int largestRectangleArea(int[] heights) {
    3. //动态规划
    4. int length = heights.length;
    5. int[] minLeftIndex = new int [length];
    6. int[] maxRigthIndex = new int [length];
    7. // 记录左边第一个小于该柱子的下标
    8. //初始化都考虑到了宽度的计算!
    9. minLeftIndex[0] = -1 ;
    10. for (int i = 1; i < length; i++) {
    11. int t = i - 1;
    12. // 这里不是用if,而是不断向右寻找的过程
    13. while (t >= 0 && heights[t] >= heights[i]) t = minLeftIndex[t];
    14. minLeftIndex[i] = t;
    15. }
    16. // 记录每个柱子 右边第一个小于该柱子的下标
    17. maxRigthIndex[length - 1] = length;
    18. for (int i = length - 2; i >= 0; i--) {
    19. int t = i + 1;
    20. while(t < length && heights[t] >= heights[i]) t = maxRigthIndex[t];
    21. maxRigthIndex[i] = t;
    22. }
    23. // 求和
    24. int result = 0;
    25. for (int i = 0; i < length; i++) {
    26. int sum = heights[i] * (maxRigthIndex[i] - minLeftIndex[i] - 1);
    27. result = Math.max(sum, result);
    28. }
    29. return result;
    30. }
    31. }

  • 相关阅读:
    pyqt教程
    2000-2023年省市县人工智能企业数量数据
    云打印api搭建,云打印api怎么对接?
    【MATLAB第74期】#源码分享 | 基于MATLAB的ARX-ARMAX线性自回归移动平均外生模型(结合最小二乘思路)
    性价比高一点的蓝牙耳机有哪几款?高性价比蓝牙耳机推荐
    Java IO基础知识总结篇一
    npm的使用
    Spring注解驱动之AnnotationAwareAspectJAutoProxyCreator的作用
    Power BI 如何使用Tooltip创建悬浮报表页 (自定义工具提示)
    [附源码]计算机毕业设计体育器材及场地管理系统Springboot程序
  • 原文地址:https://blog.csdn.net/weixin_54532276/article/details/126808214