leetcode题解-84.Largest Rectangle in Histogram

题解:给出的n个非负整数表示每个直方图的高度,每个直方图的宽均为1,在直方图中找到最大的矩形面积。

例子:给定数组: height = [2,1,5,6,2,3],返回 10 (5 * 2)
这里写图片描述

分析:总体来说首先很自然会想到暴力法解决,但是优化的方式不容易想到。自己看了网上的答案都特别抽象,看了一个多小时最后靠举例子才勉强明白怎么优化。

1、暴力法
首先,可以使用暴力破解法。以每一个数字作为高度,遍历找出左右可以匹配的最大长度。以i=2举例,左侧可以和height[2]=5组成矩形的索引为i=2本身;
右侧可以和height[2]=5组成矩形的索引为i=3;
所以对于i=2来说,最大面积就是10 (5 * 2)。
随后在不同i值对应得到的不同面积值中选出最大的一个即可。但是由于是O(n^2)复杂度,肯定过不了LeetCode的OJ,随后参照网上的过程进行优化处理。

2、栈
使用上面的例子不太方便讲解,我们在举一个例子height=[1,2,3,4,5],如下图所示:
这里写图片描述

首先,我们对数组进行扩充,height[6]=0,那么直方图变为下图;

这里写图片描述

需要用到一个栈stack,算法如下:

如果stack为空 或者 height[i] > height[stack.peek()],
那么将i的索引加入栈,并且i++;
否则,即height[i] <= height[stack.peek()]
那么出栈,然后计算对于当前i的最大面积。

i=0时,stack为空,stack.push(0);
i=1时,height[1] > height[0] ,stack.push(1);
i=2时,height[2] > height[1] ,stack.push(2);
i=3时,height[3] > height[2] ,stack.push(3);
i=4时,height[4] > height[3] ,stack.push(4);
i=5时,height[5] < height[4] ,t = stack.pop = 4,接下来的任务就是在寻找以t=4为右侧的矩形的最大面积,即:
sum = max(0, 1*5) = 5
t = stack.pop() = 3
sum = max(6, 2*4) = 8
t = stack.pop() = 2
sum = max(8, 3*3) = 9
t = stack.pop() = 1
sum = max(9, 4*2) = 9
stack.push(5) 注:此时height[5] > height[stack.pop()](即height[0])
i = i + 1 = 6
i=6时,height[6] < height[5] ,t = stack.pop = 5,接下来的任务就是在寻找以t=5为右侧的矩形的最大面积,即:
sum = max(9, 5*2) = 10
t = stack.pop() = 0
sum = max(10, 6*1) = 10
stack.push(6)
i = i + 1 = 7 (跳出循环)

返回sum=10

那么理解了代码逻辑以后,就不难写出代码:

import java.util.Stack;

public class Solution 
{
    // The main function to find the maximum rectangular area under given
    // histogram with n bars
    static int getMaxArea(int heights[]) 
    {
        Stack<Integer> stack = new Stack<>();
        int[] numbers = new int[heights.length + 1];
        for (int i = 0; i < heights.length; i++) {
            numbers[i] = heights[i];
        }
        numbers[heights.length] = 0;
        int sum = 0, i = 0;
        while (i < numbers.length) {
            if (stack.isEmpty() || numbers[i] > numbers[stack.peek()]) {
                stack.add(i);
                i++;
            } else {
                int t = stack.peek();
                stack.pop();
                sum = Math.max(sum, numbers[t] * (stack.isEmpty() ? i : i - stack.peek() - 1));
            }
        }
        return sum;
    }

    // Driver program to test above function
    public static void main(String[] args) 
    {
        int hist[] = { 1,2,3,4,5,2 };
        System.out.println("Maximum area is " + getMaxArea(hist));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值