您的位置:首页 > 理论基础 > 数据结构算法

【数据结构与算法经典问题解析】直方图中最大矩形

2016-12-30 15:30 435 查看
出自第四章问题24

问题24 直方图中的最大矩形:   直方图是由排列在同一基线上的一系列矩形组成的多边形。为了简单起见,假设这些矩形的宽度相等但高度可能不同。例如,下图1给出了一个直方图,其中各个矩形的高度为3、2、5、6、1、4、4,宽度为标准1单位。当给定了一个保存所有矩形高度的数组时,如何找到其中最大的矩形。对于给定的例子,最大矩形如图2阴影部分所示:



 图1



图2

解答:不完整子问题栈的线性搜索: 有很多种方法解决这个问题。Judege给出了一个基于栈求解问题的方法。首先按照从左到右的次序来处理元素,并将已经开始但尚未完成的子直方图保存在栈中。如果栈为空,通过将元素压入栈来开启一个字问题。否则,将元素与栈顶元素比较。如果新元素较大,那么将其入栈。如果两者相等,跳过,处理下一个元素。

    如果新元素较小,那么用栈顶元素更新最大区域,并结束最顶层的子问题,然后删除栈顶元素,保持当前新元素并重复上述这个过程(继续比较)。这样,所有的子问题都会结束,直至栈为空,或者栈顶元素小于或等于新元素,导致上述行为。若所有元素都被处理过而栈仍然不为空,那么用栈顶元素更新最大区域来结束剩余的子问题。

伪代码如下:
public class StackItem{
public int height;
public int index;
}

int MaxRectangleArea(int A[], int n){
long maxArea = 0;
if(A == null || A.length ==0)
return maxArea;
Stack<StackItem> S = new Stack<StackItem>();
S.push(new Integer.MIN_VALUE, -1);
for(int i = 0; i <= n; i++){
StackItem cur = new StackItem((i < n ? A[i] : Integer.MIN_VALUE), -1);
if(cur.height > S.top().height){
S.push(cur);
continue;
}
while(S.size > 1){
StackItem prev = S.top();
long area = (i - prev.index)*prev.height;
if(area > maxArea)
maxArea = area;
prev.height = cur.height;
if(prev.height > S.get(S.size() - 2).height){
break;
}
s.pop()
}
}
return maxArea;
}

思考: 感觉这个解法有问题,当处理{8,7,6},这样的递减数组时,会出错。下面是我修改后的代码:

package com.stack;

import java.util.Stack;

public class MaxRectangleArea {
/**
* 直方图中最大矩形问题
* 主要思路是:将所有数组以非递减循序存到栈中,当cur小于栈顶元素时,
* 将栈中所有小于cur的值替换成cur,并计算替换的这些值所能组成的最大的矩形面积;
* @param arr
* @return
*/
public static int getMaxRA(int[] arr){
int maxArea = 0;
if(arr == null || arr.length == 0)
return maxArea;
Stack<StackItem> ll = new Stack<StackItem>();
ll.push(new StackItem(Integer.MIN_VALUE, -1));//开头填入一个最小值看,while循环里有用
for(int i = 0; i <= arr.length; i++){
//当i=length时说明数组已经遍历完毕,填入一个最小值使得进入while循环,并求出栈中存储的数组最大矩形面积
StackItem cur = new StackItem(i < arr.length ? arr[i] : Integer.MIN_VALUE, i);
//当cur当前值不小于栈顶值时,存入栈
if(ll.lastElement().height <= cur.height){
ll.push(cur);
continue;
}
//当cur小于栈顶值prev时,计算prev到cur的矩形面积,并与最大矩形面积maxArea比较,
//抛出栈顶值,直到栈顶值小于当前值cur
int j = 0;
while(ll.size() > 1){
j++;
StackItem prev = ll.pop();
int area = (i - prev.index)*prev.height;
if(area > maxArea)
maxArea = area;
if( ll.lastElement().height < cur.height)
break;
}
//将抛出的值的位置用cur代替存入栈中,保持栈数据不递减
for(;j >= 0; j--){
ll.push(new StackItem(cur.height, cur.index - j));
}
}
return maxArea;
}
public static void main(String[] args) {
int[] a = {8, 7, 5, 9, 3, 8, 7, 6, 5, 4};
System.out.println("最大矩形面积为: " + getMaxRA(a));
}
}

class StackItem {
public int height;
public int index;

public StackItem(int height, int index){
this.height = height;
this.index = index;
}
}
结果:



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: