单调栈

想找 "从当前元素向某一方向的第一个 (大于 / 小于) 自己的元素",就要靠单调栈来维护单调性,对应的是 (递减 / 递增)。

例题

有N个人,顺次排列,他们的身高分别为H[i],每个人向自己后方看,他能看到的人是在他后面离他最近的且比他高的人。请依次输出每个人能看到的人的编号Next[i],如果他后面不存在比他高的人,则输出-1。

这一题用的是递减栈,当一个元素不满足栈里面的单调性的时候,这个元素就把比他小的元素都pop出去,因此每个人就都知道了第一个比自己高的元素。

public class HigherPerson {
    public static int[] getHeight(int[] heights) {
        int n = heights.length;
        int[] result = new int[n];

        // stack store index
        LinkedList<Integer> stack = new LinkedList<>();

        for (int i = 0; i < n; i++) {
            int value = heights[i];

            // error-prone: heights[stack.peek()]
            while(!stack.isEmpty() && heights[stack.peek()] < value) {
                int index = stack.pop();
                result[index] = i;
            }
            stack.push(i);
        }

        // can find higher person get -1
        while (!stack.isEmpty()) {
            result[stack.pop()] = -1;
        }

        return result;

    }
}

Largest Rectangle in Histogram

顺着上一题的思路,这题比较暴力的解法可以分为三步:

  • 从左向右扫,寻找对于每个元素,往右能看到的最远距离;
  • 从右向左扫,寻找对于每个元素,往左能看到的远距离;
  • 把两个 arr[] 的结果综合起来,就是从每个位置出发能构造的最大 rectangle.

虽然是O(n) ,但是有 three-pass。

更好的解法是,我们需要知道的是从当前点出发,找到左边第一个小于它的点的index,右边第一个小于它的点的index,高度是自己的高度,长度就是 rightIndex - leftIndex - 1 所以我们可以通过维护一个递增栈来实现,左边第一个小于它的index就是这个点在栈内左边的那个点,右边第一个小于它的点就是把它pop出去的那个点。这样通过one-pass就可以得到答案了。

public class Solution {
    public int largestRectangleArea(int[] heights) {
        if(heights == null || heights.length == 0) {
            return 0;
        }

        // store index
        LinkedList<Integer> stack = new LinkedList<>();

        int maxArea = 0;

        // ascending stack
        for(int i = 0; i <= heights.length; i++) {
            int curValue = i == heights.length ? -1 : heights[i];
            while(!stack.isEmpty() && curValue <= heights[stack.peek()]) {
                int h = heights[stack.pop()];
                int w = stack.isEmpty() ? i : i - stack.peek() - 1;

                maxArea = Math.max(maxArea, h * w);
            }
            // otherwise, keep the monotone
            stack.push(i);
        }

        return maxArea;

    }
}

results matching ""

    No results matching ""