Largest Rectangle in a Histogram (POJ - 2559 )(栈)

A histogram is a polygon composed of a sequence of rectangles aligned at a common base line. The rectangles have equal widths but may have different heights. For example, the figure on the left shows the histogram that consists of rectangles with the heights 2, 1, 4, 5, 1, 3, 3, measured in units where 1 is the width of the rectangles:
Largest Rectangle in a Histogram (POJ - 2559 )(栈)_第1张图片

Usually, histograms are used to represent discrete distributions, e.g., the frequencies of characters in texts. Note that the order of the rectangles, i.e., their heights, is important. Calculate the area of the largest rectangle in a histogram that is aligned at the common base line, too. The figure on the right shows the largest aligned rectangle for the depicted histogram.
Input
The input contains several test cases. Each test case describes a histogram and starts with an integer n, denoting the number of rectangles it is composed of. You may assume that 1<=n<=100000. Then follow n integers h1,…,hn, where 0<=hi<=1000000000. These numbers denote the heights of the rectangles of the histogram in left-to-right order. The width of each rectangle is 1. A zero follows the input for the last test case.
Output
For each test case output on a single line the area of the largest rectangle in the specified histogram. Remember that this rectangle must be aligned at the common base line.
Sample Input
7 2 1 4 5 1 3 3
4 1000 1000 1000 1000
0
Sample Output
8
4000
Hint
Huge input, scanf is recommended.

这是在挑战程序设计的一道例题,是讲解栈的应用,非常巧妙,因为自己并没有做出来,而且我也觉得这本有些例题讲的不是很清楚,对于这道题,我首先知道的是先去枚举h(高度),然后去计算这个高度的左右两个的坐标。至于怎么用栈去快速的去求这两个坐标,我觉这本书讲的不是很清楚(也许是自己太菜了hh),至于后面的代码都是自己悟的,花了大概一天的时间去思考,写这篇文章的目的是为加深理解。
分析:假设我们已经求得了这个最大矩形,那么这个矩形的高度必然是所有在这个矩形里最小的那个(短板效应),那么我们就可以枚举这个高度。确定了高度,然后去确定这个矩形的左右的两个坐标,高度是i到n的所以可能去枚举,假设h[i]为高,l[i]和r[i]为左右两个的坐标,那么矩形的面积为s=h[i]*(r[i]-l[i]+1),
好,现在问题的关键是如果去计算r[i]和l[i]
我们思考一下,我们确定h[i],那么r[i]和l[i]有什么特点。假设l[i]-1所对应的高比h[i]大,那为什么不能把l[i]的值往左移一个单位呢,但是已经l[i]已经是做左了,也就是说,h[l[i]-1]必然小于h[i],同理h[r[i]+1]必然小于h[i],这个看样例图示也可以知道。
我们从题中给的图去模拟求r[i]和l[i](设i从0开始)
当i=0,h[0]=2,因为左边已经没有多余的柱形了,所以l[0]=0;
当i=1,h[1]=1,这个时候发现h[0]>h[1],上面说了,此时对于h[0]来说r[0]就只能是0了,那么i=0时我们已经计算好了,我们就不要考虑了,而对于h[1],也恰恰因为h[0]>h[1],所以l[1]=0,可以向左边扩展。
当i=2,h[2]=4,因为h[1]

import java.util.Scanner;
import java.util.Stack;

public class Main 
{

    public static void main(String[]args)
    {
        Scanner sc=new Scanner(System.in);
        for(;;)
        {
            int n=sc.nextInt();
            if(n==0)
                break;
            Stack stack=new Stack();
            int h[]=new int[n];
            int l[]=new int[n];
            int r[]=new int[n];//上文描述
            for(int i=0;iint x=0;
            while(xwhile(!stack.isEmpty()&&h[stack.peek()]>=h[x])
                {
                    r[stack.pop()]=x-1;//出栈计算出右坐标
                }
                if(stack.isEmpty())//如果栈空,为了方便起见我们可以把这个1减到l[i]里,所有的l[i]都减1,那么s=h[i]*(r[i]-l[i])。
                {
                    l[x]=-1;//最左边是的0坐标然后减了1
                    stack.push(x);
                }
                else
                {
                    l[x]=stack.peek();
                    stack.push(x);//入栈就会计算出左坐标
                }
                x++;//考虑下一个坐标
            }
            while(!stack.isEmpty())//如果栈没有空,说明他的右坐标只能是n-1了
            {
                r[stack.pop()]=n-1;
            }
            long ans=-1;
            for(int i=0;ilong)(r[i]-l[i]));//寻找最大值即可,这里这个(long)是必须,之前没有注意,提交以后一直都是wrong answer,这里涉及了类型转化,因为题目的数据,知道是超出了int类型,但对于h[i]*(r[i]-l[i])是int类型,是这个计算完成以后才cast到long,但此时已经是溢出了,溢出了才转到了long类型(为时已晚hh),细节一定要注意
            System.out.println(ans);
        }
    }   
}

你可能感兴趣的:(数据结构,栈)