zoukankan      html  css  js  c++  java
  • 算法——柱状图中最大的矩形

    给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
    求在该柱状图中,能够勾勒出来的矩形的最大面积。
    leetcode

    解题思路:

    1. 首先想暴力该怎么做?
      就是依次遍历数组,求以每一个柱子为高度的最大面积,当遍历到一个元素的时候,在去找到它的左右两边第一个比它小的柱子的位置,这样就能取最大值。暴力的方法是N方的。
    2. 降低时间复杂度的方法。因为每次需要去遍历每个元素左右两边第一个比它小的位置,就很费时间。所以,可以先通过两次遍历,分别求每个元素在左右两个方向上,第一个比他小的元素的索引值,这样,就不需要每次都去重新找了。如果这个数组在一个方向上就是最小值,那么下标值就用-1或者数组的长度来代替计算。
    3. 通过单调栈的方法,就能通过一次遍历,寻找一个队列中,每个元素,在一个方向上的第一个比其小或者大的元素了。
    4. 最后,一次遍历数组,每次用之前存下来的左右两边第一个比它小的元素的下标之差,然后乘以其高度,就是以当前元素为高度的最大值,然后依次比较就是答案。
    class Solution {
        public int largestRectangleArea(int[] heights) {
            int n = heights.length;
            // 利用两个数组,存储每个元素左右两边第一个比它小的元素的下标
            int[] l = new int[n], r = new int[n];
            Deque<Integer> stack = new LinkedList<>();
            int res = 0;
    
            for(int i = 0; i < n; i++) {
            	// 如果栈顶元素比它大,就不断弹出,因为在之前的比它大的元素已经不会被用到了
                while(!stack.isEmpty() && heights[stack.peek()] >= heights[i]) {
                    stack.pop();
                }
    			// 弹到最后剩下的,就是第一个比它小的元素了
                l[i] = stack.isEmpty() ? -1 : stack.peek();
    
                stack.push(i);
            }
    
            stack = new LinkedList<>();
            for(int i = n - 1; i >= 0; i--) {
                while(!stack.isEmpty() && heights[stack.peek()] >= heights[i]) {
                    stack.pop();
                }
    
                r[i] = stack.isEmpty() ? n : stack.peek();
    
                stack.push(i);
            }
    
            for(int i = 0; i < n; i++) {
                res = Math.max(res, heights[i] * (r[i] - l[i] - 1));
            }
    
            return res;
        }
    }
    
  • 相关阅读:
    powershell,系统学习的第一种脚本语言
    mysql的source命令
    timer--计时器
    document.write 方法
    数组去重
    Abdicate
    轮播图
    使用 margin 让div块内容居中
    模运算 NOJ 1037
    模运算 NOJ 1037
  • 原文地址:https://www.cnblogs.com/lippon/p/14117630.html
Copyright © 2011-2022 走看看