单调栈的应用(leetcode 85 maximal_Recetangle leetcode 84 largest_rectangle_in_histogram)

笔试面试中,单调栈用的也特别多,属于数据结构类的,在这里先总结下,免得以后忘了。这里只讲应用,不太设计原理。
首先来个经典例题:
求矩形的最大面积。
这个题目就是典型的单调栈。
运用单点栈的时候,首先想到的,应该是,建立一个单调递增还是单调递减的单调栈。这里维护一个单调递增的单调栈。每次遇到一个小于当前栈顶的数时(假设这个数为tn),把当前栈中所有比tn大的数,全部弹出栈。弹出栈的过程中,不要忘了,在弹出的过程中,不要忘了做相应的操作(如增加矩形的宽)。
以这组数据为例:
3 5 10 12 7 8 20
刚开始面积s = 0,首先把3入栈,然后5大于3,5入栈,10大于5,10入栈,12大于10,12入栈,7小于12,12出栈,同时s 更新为12;10比7大,10出栈,更新s为10*2 = 20。然后7入栈,这个时候,7的宽为3(10,12,7,三个数全部压成了7)。8入栈,20入栈。所有数遍历完了之后,栈中内容为3(1),5(1),7(3),8(1),20(1),s=20。20出栈,s=20,8出栈,s=max(s,8*2)=20,6出栈,s=max(s,6*5) = 30。。。这样操作下去。
贴出这个题目AC的代码:


    class R {
        public int x;
        public int y;

        public R(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    public int largestRectangleArea(int[] height) {
        if(height.length==0)
            return 0;

        Stack<R> stack = new Stack<>();
        //维护一个单调递zeng的单调栈
        int pos = 0;
        int max = 0;
        stack.add(new R(height[pos++], 1));
        while (pos < height.length) {
           \\ R tr = stack.peek();
            int len = 1;
            while (!stack.isEmpty() && (stack.peek().x > height[pos])) {
                len += stack.peek().y;
                max = Math.max((len - 1) * stack.peek().x, max);
                stack.pop();
            }
            stack.push(new R(height[pos++], len));
        }
        int len = 0;
        while (!stack.isEmpty()) {
            len += stack.peek().y;
            max = Math.max(max, len * stack.pop().x);
        }
     \\   System.out.print(max);
        return max;
    }

这是单调栈的一个典型应用,还有一个变形就是 给你一连串数字,要你找出一连串连续的数字,求出该区间段中所有数的和*该区间中最小值,也是单调栈的典型应用。
单调栈的时间复杂度,几乎可以认为为线性。
一维单调栈就说这么多吧,下面说说二维单调栈。
先来一个二维单调栈的典型题目。
leetcode最大矩形面积
这里是二维单调栈的典型应用,遍历数组,每一层当做一个一维的单调栈去处理。关键在于得到单调栈的矩形,这个矩形由上面的矩形传递下来。如果当前a[i]为0,则这个矩形高度为0,如果a[i]为1,则矩形面积为a[i-1]+1。
AC代码如下:

    class R {
        int x;
        int y;
        public R(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }
    int dp[][];
    public int maximalRectangle(char[][] matrix) {
        if (matrix.length == 0)
            return 0;
        int len1 = matrix.length;
        int len2 = matrix[0].length;
        dp = new int[len1][len2];
        for (int i = 0; i < len1; i++) {
            for (int j = 0; j < len2; j++) {
                dp[i][j] = 0;
            }
        }
        for (int i = 0; i < len2; i++) {
            dp[0][i] = matrix[0][i] == '1' ? 1 : 0;
        }
        Stack<R> stack = new Stack<>();
        int a[] = new int[len2];
        a[0] = matrix[0][0] == '1' ? 1 : 0;
        int max = a[0];
        for (int i = 1; i < len2; i++) {
            if (matrix[0][i] == '1') {
                a[i] = a[i - 1] + 1;
                max = Math.max(max, a[i]);
            } else {
                a[i] = 0;
            }
        }
        for (int i = 1; i < len1; i++) {
            for (int j = 0; j < len2; j++) {
                if (matrix[i][j] == '1') {
                    dp[i][j] = dp[i - 1][j] + 1;
                }
                int len = 1;
                while (!stack.isEmpty() && (stack.peek().x > dp[i][j])) {
                    len = len + stack.peek().y;
                    max = Math.max(max, (len - 1) * stack.peek().x);
                    stack.pop();
                }
                stack.push(new R(dp[i][j], len));
            }
            int slen = 0;
            while (!stack.isEmpty()) {
//                System.out.print(stack.peek().x + " " + stack.peek().y + " ");
                slen += stack.peek().y;
                max = Math.max(max, stack.peek().x * slen);
                stack.pop();
            }
//            System.out.println();

        }
        return max;
    }

这时复杂度就是在一维单调栈上面加一维。

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_33277870/article/details/79955118
个人分类: 算法 笔试
上一篇动态规划小结2
下一篇动态规划3
想对作者说点什么? 我来说一句

leetcode solution

2018年06月07日 1.15MB 下载

没有更多推荐了,返回首页

关闭
关闭