zoukankan      html  css  js  c++  java
  • leetcode84

    Given n non-negative integers representing the histogram's bar height where the width of each bar is 1, find the area of largest rectangle in the histogram.
    Example:
    Input: [2,1,5,6,2,3]
    Output: 10
     
     
    Stack 递增栈。
    想法:遍历的时候,把当前条条和以前的(stack.peek)对比。
    当你看到条条比peek高,你知道当前这根条条有希望合并到之后一些条条的答案里(因为后面可能还是递增的),你就先偷懒。只是压入栈,不处理。
    当你看到条条比peek矮,比如看到了heights[4] = 2 < 6你不能偷懒了要开始对stack里之前的东西进行一些计算了。计算方法就是在peek比当前条条还高着的情况下,不断pop以前的条条,通过高宽计算面积去打擂台。算完才把这个小矮条压入栈给以后用。
    1)高就是当前pop出来的这条的高度,比如5.
    2)宽就是被夹在中间的那一段,左边是现在的peek(不被算在内 peek: 如1),右边是遍历过程中的新矮条位置(i: 如4) 这两个左右定位符都不被包括在内,例如此时算出来的宽度是4-1-1。另外解释一下,我们选择这个固定下来anchor住的右边的原因是,我们知道stack里一直递增状态,当我们pop到当前这个位置的时候,我知道之前被pop出来的那些肯定也有当前这条那么高,所以我肯定可以一直延伸到新矮条前面的。
     
    细节:
    1.如果遍历完一次后,stack里还剩下东西,还要继续用类似方法处理,这次就是把右边定位在最后一根条条的右边。这个计算可以通过小trick合并到前面的遍历内。
    2.如果pop后要算长宽时,发现stack空了,那宽度就是让左边看成index-1了,也就是左边的条条全都包括进来按当前height计算。因为你能把递增栈stack掏空说明你现在pop出来的这条,是你见过有史以来最矮的一条,那么所有前面的都可以贡献了。
     
    这题好难,多跑test多体会多回顾code。
     
    实现1:代码有冗余,但思路直接一些
    class Solution {
        public int largestRectangleArea(int[] heights) {
            int ans = 0;
            Stack<Integer> stack = new Stack<>();
            
            for (int i = 0; i < heights.length; i++) {
                if (stack.isEmpty() || heights[i] >= heights[stack.peek()]) {
                    stack.push(i);
                } else {
                    while (!stack.isEmpty() && heights[i] < heights[stack.peek()]) {
                        int height = heights[stack.pop()];
                        int width = stack.isEmpty() ? i : i - 1 - stack.peek();
                        ans = Math.max(ans, height * width);
                    }
                    stack.push(i);
                }
            }
            
            // for the case after all the iteration, there's still elements left in the stack.
            while (!stack.isEmpty()) {
                int height = heights[stack.pop()];
                int width = stack.isEmpty() ? heights.length : heights.length - 1 - stack.peek();
                ans = Math.max(ans, height * width);
            }
            return ans;
        }
    }

    实现2:九章,去除冗余,有一些小trick。

    public class Solution {
        public int largestRectangleArea(int[] height) {
            if (height == null || height.length == 0) {
                return 0;
            }
            
            Stack<Integer> stack = new Stack<Integer>();
            int max = 0;
            for (int i = 0; i <= height.length; i++) {
                int curt = (i == height.length) ? -1 : height[i];
                while (!stack.isEmpty() && curt <= height[stack.peek()]) {
                    int h = height[stack.pop()];
                    int w = stack.isEmpty() ? i : i - stack.peek() - 1;
                    max = Math.max(max, h * w);
                }
                stack.push(i);
            }
            
            return max;
        }
    }
     
  • 相关阅读:
    JS基础学习四:绑定事件
    常用JS事件对象
    jq 使用手册
    access数据库根据指定日期进行查询
    IP地址变动后,https://localhost:1158/em无法访问解决办法
    结构体对齐方式
    宏得到当前函数的名字
    std::list保存大量数据时,类型即是无析构函数,该list析构时会占用大量CPU
    装了vs2010 SP1后,开机速度慢
    查询SQL Server版本号
  • 原文地址:https://www.cnblogs.com/jasminemzy/p/9764297.html
Copyright © 2011-2022 走看看