LeetCode_Stack_Largest Rectangle in Histogram
2015-06-28 01:25
232 查看
84. Largest Rectangle in Histogram
1. 问题描述:
输入是一个int数组,代表如图的直方图。要求输出是直方图能够覆盖的最大面积。
2. 解题思路:
直白的看这道题,最大的面积一定是从某个柱出发,向左向右延展,然后得到最大的面积。于是问题来了,从哪个柱开始延展,延展到哪个柱就能得到最大的面积。首先,如题目图中示例,我们先把目光聚焦到5,6,2这三根柱,忽略掉其他的柱。图中已经画出5,6覆盖了最大面积,想象如果继续向右延伸到2,那么2这根柱势必拉低了5,6覆盖面积的成果。但如果是5,6,7,那么势必要向右延伸到7,并且5,6,7覆盖的面积一定大于5,6覆盖的面积。这样我们就得出一个结论:如果遍历到下个柱是递增趋势,那么一定要延展到下一个柱。
得到这个结论之后,题目就好解了。为了好理解这里的解决思路,我们使用了两个栈,栈 index_stackindex\_stack 存储递增柱的索引值(之后计算覆盖矩形面积的长),栈 height_stackheight\_stack 存储递增柱的值(之后计算覆盖矩形面积的高)。所以我们只去计算栈中柱所覆盖的最大面积。面积计算的公式就是:S=(i−(left−1)−1)∗height_stack.pop() S= (i - (left-1) -1) * height\_stack.pop() 。这里(i−(left−1)−1)(i - (left-1) -1) 就是覆盖矩形面积的长, i 是现在遍历到的柱的索引值,left−1left-1 是index_stackindex\_stack 的栈顶元素减一。height_stack.pop()height\_stack.pop()就是存柱值的栈顶元素。
拿题目图中示例演示其中一个阶段。当1,5,6在栈中,此时指针已经遍历到2。
那么2因为递减趋势,不加入栈中,开始计算面积。 (i−(left−1)−1)(i - (left-1) -1) 中的 ii 就是2所在的索引值,left−1left-1 是5所在的索引值。height_stack.pop()height\_stack.pop() 就是6。这时计算的就是6这个柱的面积,把这个面积和当前最大面积比较,比当前面积大就替换。然后弹出6柱和其索引。
比较指针所在的2柱和此时栈顶元素5,发现仍是递减,那继续计算面积,就是(2柱索引值−1柱索引值−1)∗5(2柱索引值 - 1柱索引值 -1)* 5,就是5向右延伸到6的面积。比较面积替换,然后弹出5柱和其索引。
比较指针所在的2柱和此时栈顶元素1,发现此时是递增,那么把2柱加入 height_stackheight\_stack,同时把 leftleft 加入 index_stackindex\_stack 中。这里要注意,为什么不加入2柱所在的索引,而要加入 leftleft。原因很简单,这里 leftleft 是 5 柱所在的索引值,可以当成 5,6 柱现在柱高都是2。当指针扫到最后为空时,计算2柱覆盖面积时,覆盖矩阵的长度要包括5和6。
大致思路就是这样,代码具体的还要注意边界的处理。这里是用了两个栈,其实也可以只用一个栈,减少算法的空间复杂度。
3. java代码
public class Solution { public int largestRectangleArea(int[] height) { if(height.length == 0) return 0; int largest_area = 0; Stack<Integer> height_stack = new Stack<Integer>();//存放递增的柱 Stack<Integer> index_stack = new Stack<Integer>();//存放递增柱的索引 for(int i=0;i<height.length;i++){ if(height_stack.empty() || height_stack.peek()<=height[i]){ //增加递增柱 index_stack.push(i); height_stack.push(height[i]); } else { //error int left = 0; //左边界 while(!height_stack.empty() && height_stack.peek()>height[i]){//依次弹出栈顶元素,直到栈顶元素小于当下索引的元素 left = index_stack.pop(); int cur_area = (i - (left-1) -1) * height_stack.pop(); //跨度 i - j - 1 if(cur_area>largest_area) { largest_area = cur_area; } } height_stack.push(height[i]); index_stack.push(left); } } while(!height_stack.empty()){ int cur_area = (height.length - (index_stack.pop()-1)-1) * height_stack.pop(); if(cur_area>largest_area){ largest_area = cur_area; } } return largest_area; } }
4. 算法评估
希望大家多多指正交流。
相关文章推荐
- 灵悟礼品网上专卖店——总结
- Runtime.getRuntime().exec()----记录日志案例
- Codeforces Round #310 (Div. 1) B. Case of Fugitive set
- 数学之美-阅读笔记
- Java基础:动态代理在RPC框架中应用
- Oracle ->> ENABLE VALIDATE & DISABLE VALIDATE
- Tempter of the Bone
- 在JSP前台和后台传递参数乱码汇总
- Java基础:静态代理和动态代理
- A* Pathfinding Algorithm
- php 数组与数据结构
- 常用代码总结(一)
- 第一次博客2015/06/27
- 进程的退出exit() --多进程编程
- SQL注入原理讲解,很不错!
- android-数据库SQLite相关
- Javascirpt 作用域
- php页面静态化—静态化详细介绍
- java当前日期增加天数
- 命令别名与历史命令 alias,history