leetcode 84 Largest Rectangle in Histogram (单调栈)

上题目

题目大意为:给一个数组代表一个柱状图,数组中每一个元素依次代表柱状图中每个“柱”的高,求这个柱状图能包含的最大矩形面积。

思考:最终矩形的高一定等于某个“柱”的高,宽为这个“柱”左右能延伸到的最大距离之和(直到遇见某个“柱”的高低于当前高)。暴力就是对于每一个“柱”,向左和向右延伸到极限得出宽,再乘以高,复杂度是n的平方。

可以用单调栈(栈中的元素单调递增)对这个过程进行简化,栈中每个元素包含两个属性,一是“柱”高(设为x),二是以这个柱高向左能延伸到的最远距离(设为y,y包括柱本身的宽度1,故y初值为1),由栈底到栈顶每个元素的柱高x依次递增,栈顶元素柱高x最大。

整个算法由不断的入栈和出栈构成,将给定的数组元素依次入栈,入栈时计算当前元素向左能延伸到的最远距离,定义后面要用到的累加宽度w = 0,入栈时有两种可能:

(1)栈顶元素柱高大于当前元素柱高,出栈(保证栈的单调性,且此时可以计算面积,后面再说)。累加出栈元素的宽度(这个累加宽度代表的是:新的栈顶元素可以向右延伸这个宽度,这也是用递增栈的原因,由于出栈元素高于新的栈顶元素,那么出栈元素向左能延伸到的最远处,新的栈顶元素至少也能向右延伸到),若栈不空且出栈后新的栈顶元素柱高仍高于当前元素,继续(1)

  (2)  栈顶元素柱高小于当前元素柱高,此时当前元素直接入栈,当前元素的y = 1+w,w代表当前元素之前所有高于当前元素的元素宽度之和,即当前元素可以向左延伸至1+w

出栈时,出栈元素向右能延伸的距离为当前w,故面积为(w+y)*x,计算并更新最大面积。

例如对于题中[2,1,5,6,3,2],以(x,y)表示栈中元素,max代表最大面积

(2,1)准备进栈,初始化w = 0,发现栈空,进栈

(1,1)准备进栈,初始化w = 0,发现其柱高小于栈顶元素,(2,1)出栈,计算面积得 2*1 = 2,max = 2

累加宽度w = w + 1 = 1,y = 1+w = 2,(1,2)进栈

(5,1)准备进栈,初始化w = 0,发现栈顶元素柱高小于当前元素,进栈

(6,1)进栈,同上,此时栈中元素为(1,2)(5,1)(6,1)

 

(2,1)准备进栈,初始化w = 0,发现其柱高小于栈顶元素,(6,1)出栈,计算面积得 6*1 = 2,max = 6

累加宽度w = w + 1 = 1,接着(5,1)出栈,计算面积得(1 + 1)*5 = 10,max = 10,累加宽度w = w + 1 = 2,出栈完毕。y = 1 + w = 3,(2,3)进栈,此时栈中元素为(1,2)(2,3)

(3,1)进栈,此时栈中元素为(1,2)(2,3)(3,1)

将栈中剩余元素依次出栈:

初始化w = 0,(3,1)出栈,计算面积得 3*1 = 8,max不变,累加宽度w = w + 1 = 1,接着(2,3)出栈,计算面积得(1+3)*2 = 8,max不变,累加宽度w = w + 3 = 4,接着(1,2)出栈,计算面积得(4+2)*1 = 6,面积不变,出栈完毕。

最终max = 10

上AC代码:

class Solution {
    private static class Node{
        public int height;
        public int weight;

        public Node(int height, int weight) {
            this.height = height;
            this.weight = weight;
        }
    }
    public int largestRectangleArea(int[] heights) {
        if(heights==null||heights.length==0)
            return 0;
        int max = 0;
        Stack<Node> stack = new Stack<>();
        int index = 0;
        stack.push(new Node(heights[index++],1));
        Node temp;
        int areaSize ,count;
        for(;index<heights.length;index++) {
            count = 0;
            while (!stack.empty() && stack.peek().height >= heights[index]) {
                temp = stack.pop();
                count += temp.weight;
                areaSize = temp.height*count;
                max = max > areaSize ? max : areaSize;
            }
            stack.push(new Node(heights[index],count+1));
        }
        count = 0;
        while (!stack.empty()){
            temp = stack.pop();
            count += temp.weight;
            areaSize = temp.height*count;
            max = max > areaSize ? max : areaSize;
        }
        return max;
    }
}

PS:开始在POJ 2559 (题目一样)上提交,怎么改都是wrong answer,后来只好去leetcode,发现是函数的最开始没有判断数组是否为空 orz,以后一定记得判断!!!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值