Friday, September 27, 2013

Largest Rectangle in Histogram !!!!!!!!!!!!!!!!

Q:
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.

A:
--------------4 rd -------------------依然是用2个stack--------------------
 代码看2nd实现。
犯的错误:
1:当要pop出indexstack之后, 要push进去的,不是当前的i,而是当前最远到达的index(因为之后的,都至少是这个height[i]的高度。
2:  while的时候,没有先检查是否是stack.isEmpty()





 ------------------------1  st ------------------naive way--------------------
经过分析,首先的一个思路,就是,假设某个bar是最低的一个,向左右发展,得到其面积。
哎,也就是说,对for position i,   treat height[i] as the ceiling, calcualte the area.

由于重复计算,代码效率不高。 代码如下

public class Solution {
   public int largestRectangleArea(int[] height) {
        int n = height.length;
        // recording the maximum area , if we assume current position bar is the
        // lowest
        int[] maxAreaHere = new int[n];
        int maxArea = 0;
        for (int i = 0; i < n; i++) {
            // we assume that current bar is the lowest
            // calculate the
            maxAreaHere[i] = height[i];
            // calculate the adjacent left areas,
            int left = i - 1;
            while (left >= 0 && height[left] >= height[i]) {
                maxAreaHere[i] += height[i];
                left--;
            }
            // calculate the adjacent right areas,
            int right = i + 1;
            while (right < n && height[right] >= height[i]) {
                maxAreaHere[i] += height[i];
                right++;
            }
            if (maxArea < maxAreaHere[i]) {
                maxArea = maxAreaHere[i];
            }
        }
        return maxArea;
    }
}

上述解法,会有TLE错误(time Limit exceed )
原因就出在 重复计算上。
网上的解法   GeeksforGeeks       Youtube.                别人的博客
思路如下:
依次加入 每个bar,加入的时候,其与之前的bar们,组成的rectangle的面积。
Solution:
Use Stack to keep track of height and start indexes
Compare current height with previous one

#1: current Larger than previous (top of height stack)
Push current height & index as candidate rectangle start position

#2: current EQUALS previous
Ignore, as largest rectangle will start from previous with same height

#3: current is less than previous
Need keep popping out previous heights, and compute the candidate rectangle with height and width (current index MINUS previous index)
Push the height and index (appropriate position) to stacks

public int largestRectangleArea(int[] height) {
        Stack<Integer> stkH = new Stack<Integer>();// stack recording the height
                                                    // of bar
        Stack<Integer> stkIndex = new Stack<Integer>();// stack recording
                                                        // correspnding index
        int maxArea = 0;
        for (int i = 0; i <  height.length; i++) { // for each length
            // if current bar is higher than previous, push
            if (stkH.isEmpty() || stkH.peek() > height[i]) {
                stkH.push(height[i]);
                stkIndex.push(i);
            } else if (stkH.peek() < height[i]) {
                // if current bar is shorter, we need pop out those longer
                // heights
                // and compute the candidatesrectangle's area and update maxArea
                int lastIndex = 0;// this index to keep track of the last index
                                    // ,which wil lbe repalceing the current
                                    // height inserting
                while (!stkH.isEmpty() && stkH.peek() < height[i]) {
                    // we need compute the size
                    lastIndex = stkIndex.pop();
                    int tmpSize = stkH.pop() * (i - lastIndex);
                    if (maxArea < tmpSize)
                        maxArea = tmpSize;
                }
                // after popping those unqualifed start position, including
                // current index,
                // we add those back , but now, current bar is the lowest from
                // lastIndex ..... i
                stkH.push(height[i]);
                stkIndex.push(lastIndex);
            }
        }
        // after the process, there might still be values in stacks, pop out
        // each other and test size
        while (!stkH.isEmpty()) {
            // we need compute the size, ( from current , down to the most left
            // bar, --- height[0]
            // the width = currentIndex(lat one) - height[i]
            // -------- just imagining we add bar of zero at most right
            int tmpSize = stkH.pop() * (height.length - stkIndex.pop());
            if (maxArea < tmpSize)
                maxArea = tmpSize;
        }
        return maxArea;
    }



Mistakes:


Learned:



------------------------------------------第二遍------------------------------------
思路同上面,那个跟人学的一样

只不过,对于2个stack,我们用一个stack<int[]>代替了。int[] 的长度为2, 第一个是height[i],第二个是index, 表明了,到这个height的之前的,连贯的(大于等于该height的)最远距离。

public class Solution {
      public int largestRectangleArea(int[] height) {
        int maxSize = 0;
        if (height.length <= 0)
            return maxSize;
        // assume just inserted bar is the lowest, and calculate the area
        Stack<int[]> stack = new Stack<int[]>(); // int[] =={height, index}
        for (int i = 0; i < height.length; i++) {
            if (stack.isEmpty() || stack.peek()[0] < height[i]) {
                int[] tmp = { height[i], i };
                stack.push(tmp);
            } else if (stack.peek()[0] >  height[i]) {
                int lastIndexGreaterThanCurrent = i; // greater than height[i]
                while (!stack.isEmpty() && stack.peek()[0] > height[i]) {
                    // pop the curent stack
                    int[] tmp = stack.pop();
                    lastIndexGreaterThanCurrent = tmp[1];
                    int curSize = tmp[0] * (i - tmp[1] );
                    maxSize = Math.max(maxSize, curSize);
                }
                // push the current value
                int[] tmp = { height[i], lastIndexGreaterThanCurrent };
                stack.push(tmp);
            }
        }
        // deal with the case that stack is not empty
        while (!stack.isEmpty()) {
            int[] tmp = stack.pop();
            int curSize = tmp[0] * (height.length - tmp[1]);
            maxSize = Math.max(maxSize, curSize);
        }
        return maxSize;
    }
}

-------------------------第三遍-----------------------
再一次强调,  当现在的height[i]的值更小的时候,  我们要计算的,是在它之前的所有的面积, 而不是包括它的面积。!!!!!!!!!!!!!!!1
Tiger,   再仔细看看, 那几行代码吧。。。。





Mistakes:
1:  两个index相减, 其长度应该是要加1 的。 哎,丢人,这么SB的错误
2:刚开始的这个思想根本就是不对的。 当stack.peek() < height[i]的时候,我们应该计算的,是对于所有大于height[i]这个高度的 和

Learned:


No comments:

Post a Comment