单调栈相关
2015-06-04 08:52
453 查看
1. 利用单调栈求最大矩形面积(两边求)
来源poj: http://poj.org/problem?id=2082 ;
leetcode: https://leetcode.com/problems/largest-rectangle-in-histogram/
题目:
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. Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3]. The largest rectangle is shown in the shaded area, which has area = 10 unit. For example, Given height = [2,1,5,6,2,3], return 10.
思路:
正常一个方法为:遍历数组中的矩形底,以每个index的底为中心向两边扩张得到以此index为高的最大矩形面积,最后求出全局最大。时间复杂度为O(n^2),空间复杂度为O(1)
单调栈的想法是:维护一个栈,这个栈中的元素保持单调,例如单调递增栈是,只要遍历到的元素大于栈顶元素就压入栈,否则,不断弹出栈顶元素直到当前栈顶元素小于当前遍历元素。
本题解题思路:顺着第一个题的思路,对于每个底边需要向两边扩张找到以它为高的最远边界,那么也就是找到周围都比它高的最远边界。因此,问题就转化为找到一个边左边比它高的边长总和以及右边比它高的边长总和。在单调栈中,当某个元素可以进栈了,说明栈顶元素一定是其左边最高边界(的下一个,或者说第一个比它矮的)。而当一个元素需要出栈时,说明遇到了右边边界(第一个比它矮的)。利用这样的性质,就可以在O(n)的时间内得到结果。
ps:单调栈可以解决需要计算一个元素两边大于它或者两边小于它的边界问题。
@Checked public int largestRectangleArea(int[] height) { if(height == null || height.length == 0) return 0; Deque<Integer> deque = new ArrayDeque<Integer>(); int[] area = new int[height.length]; int largest = 0; for(int i = 0; i < height.length; i++){ //左边没有连续比当前元素大的元素 if(deque.size() == 0 || height[deque.peekLast()] <= height[i]) deque.add(i); //当有比当前元素大的元素,要弹出比它大的,计算弹出元素右边面积,最后压入当前元素,计算当前元素左边面积。注意相等的情况下 else{ int index = 0; while(deque.size() != 0 && height[deque.peekLast()] > height[i]){ index = deque.pollLast(); area[index] += (i - index) * height[index]; largest = largest > area[index] ? largest : area[index]; } index = deque.size() == 0 ? -1 : deque.peekLast(); area[i] += (i - index -1) * height[i]; deque.add(i); } } while(deque.size() != 0){ int index = deque.pollLast(); area[index] += (height.length - index) * height[index]; largest = largest > area[index] ? largest : area[index]; } return largest; }
由于此处需要存储左边右边,实际上可以减少存储,在元素弹出时计算其整体面积。为防止后面多加一层循环,可以在数组最后放置一个哨兵。可以简化很多代码
@Checked public int largestRectangleArea(int[] height) { if(height == null || height.length == 0) return 0; Deque<Integer> deque = new ArrayDeque<Integer>(); int largest = 0; for(int i = 0; i <= height.length; i++){ int pivot = i == height.length ? 0 : height[i]; while(deque.size() != 0 && height[deque.peekLast()] > pivot){ int index = deque.pollLast(), pre = deque.size() == 0 ? -1 : deque.peekLast(); int high = (i - pre - 1) * height[index]; largest = largest > high ? largest : high; } deque.add(i);//统一操作 } return largest; }
2. 类似题目:牛视野问题(只求一边)
poj http://poj.org/problem?id=3250= = = = - = Cows facing right --> = = = = - = = = = = = = = = 1 2 3 4 5 6 Cow#1 can see the hairstyle of cows #2, 3, 4 Cow#2 can see no cow's hairstyle Cow#3 can see the hairstyle of cow #4 Cow#4 can see no cow's hairstyle Cow#5 can see the hairstyle of cow 6 Cow#6 can see no cows at all!
每只牛都向右看,遇到比它高的就看不到了,因此找的是比它低的。求所有牛能看到的牛的总和。
本题意义是找到每个底右边比它低的,即使用单调递减栈,每次弹出时计算整个右边边界即可。
public int numbersOfCows(int[] height){ Deque<Integer> deque = new ArrayDeque<Integer>(); int count = 0; for(int i = 0; i <= height.length; i++){ int pivot = i == height.length ? Integer.Max_VALUE : height[i]; while(deque.size() != 0 && pivot > height[deque.peekLast()]){ int index = deque.pollLast(); count += (i - index - 1); } deque.add(i); } return count; }
**inspiration:遇到总和各局部周围情况(比它小或者大)求整体最优可以考虑单调栈解法。
相关文章推荐
- 部分计算机视觉数据集汇总
- Netty的分隔符和定长解码器应用
- output存储一列
- Java引用外包
- UCOSii(四)——任务的通信与同步
- 文本框中默认显示出用户名,当输入名字的时候会覆盖用户名
- 团队成员分工
- Oracle 游标使用全解(转)
- 作为一个医疗外推,我也需要爱情
- android (13) Fragment使用下
- android Navigator的高度计算和判断是否显示
- web-inf存放jsp的注意事项
- Java路上,必看书籍
- Java类与对象的初始化
- 十六、Qt 2D绘图(六)坐标系统
- Java中的参数传递方式
- Hibernate判断某属性不为null 且不可为空时出现Property path [...] does not reference a collection 的问题
- WebService 的简单封装接口调用方法
- 实现listView的不同布局item
- 实现表单form提交前进行确认提示 表单提交 确认对话框