【leetcode-单调栈】柱状图中的最大矩形/最大矩形/矩形面积/下一个更大元素

本文详细介绍了如何使用单调栈解决柱状图中寻找最大矩形面积的问题,以及在二维矩阵中找到最大矩形面积的算法。这两种情况都涉及到了栈的数据结构和单调性的应用,通过不断比较和更新当前高度,计算出最大矩形的边界,最终得出最大面积。此外,还提到了如何找到数组中每个元素的下一个更大元素,同样利用了单调栈的特性。
摘要由CSDN通过智能技术生成

柱状图中的最大矩形

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。

以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]。
在这里插入图片描述
图中阴影部分为所能勾勒出的最大矩形面积,其面积为 10 个单位。
示例:
输入: [2,1,5,6,2,3]
输出: 10

单调栈

class Solution {
    public int largestRectangleArea(int[] heights) {
        int n = heights.length;
        int[] left = new int[n];
        int[] right = new int[n];
        Stack<Integer> stack = new Stack<>();
        for (int i = 0; i < n; ++i) {
            while (!stack.isEmpty() && heights[stack.peek()] >= heights[i])
                stack.pop();
            left[i] = stack.isEmpty() ? -1 : stack.peek();
            stack.push(i);
        }

        stack.clear();
        for (int i = n - 1; i >= 0; --i) {
            while (!stack.isEmpty() && heights[stack.peek()] >= heights[i])
                stack.pop();
            right[i] = stack.isEmpty() ? n : stack.peek();
            stack.push(i);
        }

        int max = 0;
        for (int i = 0; i < n; i++) 
            max = Math.max(max, (right[i] - left[i] - 1) * heights[i]);
        return max;
    }
}

单调栈 + 常数优化

class Solution {
    public int largestRectangleArea(int[] heights) {
        int n = heights.length;
        int[] left = new int[n];
        int[] right = new int[n];
        Arrays.fill(right, n);
        Stack<Integer> stack = new Stack<>();
        for (int i = 0; i < n; ++i) {
            while (!stack.isEmpty() && heights[stack.peek()] >= heights[i]) {
                right[stack.peek()] = i;
                stack.pop();
            }
            left[i] = stack.isEmpty() ? -1 : stack.peek();
            stack.push(i);
        }

        int max = 0;
        for (int i = 0; i < n; i++) 
            max = Math.max(max, (right[i] - left[i] - 1) * heights[i]);
        return max;
    }
}

左右两边增加元素

class Solution {
    public int largestRectangleArea(int[] heights) {
        int n = heights.length;
        int[] newHeights = new int[n + 2];
        newHeights[0] = 0;
        newHeights[n + 1] = 0;
        System.arraycopy(heights, 0, newHeights, 1, n);
        n += 2;

        int max = 0;
        Deque<Integer> stack = new LinkedList<>();
        stack.push(0);
        for (int i = 1; i < n; i++) {
            while (newHeights[i] < newHeights[stack.peek()]) {
                max = Math.max(max, newHeights[stack.pop()] * (i - stack.peek() - 1));
            }
            stack.push(i);
        }
        return max;
    }
}

最大矩形

给定一个仅包含 0 和 1 、大小为 rows x cols 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。

示例 1:
在这里插入图片描述
输入:matrix = [[“1”,“0”,“1”,“0”,“0”],[“1”,“0”,“1”,“1”,“1”],[“1”,“1”,“1”,“1”,“1”],[“1”,“0”,“0”,“1”,“0”]]
输出:6
解释:最大矩形如上图所示。

示例 2:
输入:matrix = []
输出:0

示例 3:
输入:matrix = [[“0”]]
输出:0

示例 4:
输入:matrix = [[“1”]]
输出:1

示例 5:
输入:matrix = [[“0”,“0”]]
输出:0

暴力法

class Solution {
    public int maximalRectangle(char[][] matrix) {
        int rows = matrix.length; 
        if (rows == 0)
            return 0;
        int cols = matrix[0].length;
        
        int[][] left = new int[rows][cols];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (matrix[i][j] == '1')
                    left[i][j] = (j == 0 ? 0 : left[i][j - 1]) + 1;
            }
        }

        int max = 0;
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (matrix[i][j] == '1') {
                    int width = left[i][j];
                    int area = width;
                    for (int k = i - 1; k >= 0; k--) {
                        if (left[k][j] == 0)
                            break;
                        width = Math.min(width, left[k][j]);
                        area = Math.max(area, (i - k + 1) * width);
                    }
                    max = Math.max(area, max);
                }
            }
        }
        return max;
    }
}

单调栈

与柱状图中的最大矩形相似
在这里插入图片描述

class Solution {
    public int maximalRectangle(char[][] matrix) {
        int rows = matrix.length; 
        if (rows == 0)
            return 0;
        int cols = matrix[0].length;
        
        int[] heights = new int[cols + 1];
        int maxArea = 0;
        for (int i = 0; i < rows; i++) {
            Stack<Integer> stack = new Stack<>();
            heights[cols] = 0;
            for (int j = 0; j <= cols; j++) {
                if (j < cols) {
                    if (matrix[i][j] == '1')
                        heights[j] += 1;
                    else
                        heights[j] = 0;
                }

                if (stack.isEmpty() || heights[j] >= heights[stack.peek()]) {
                    stack.push(j);
                } else {
                    while (!stack.isEmpty() && heights[j] < heights[stack.peek()]) {
                        int height = heights[stack.pop()];
                        int left = stack.isEmpty() ? -1 : stack.peek();
                        int area = (j - left - 1) * height;
                        maxArea = Math.max(area, maxArea);
                    }
                    stack.push(j);
                }
            }
        }
        return maxArea;
    }
}

矩形面积

在二维平面上计算出两个由直线构成的矩形重叠后形成的总面积。
每个矩形由其左下顶点和右上顶点坐标表示,如图所示。
在这里插入图片描述

示例:
输入: -3, 0, 3, 4, 0, -1, 9, 2
输出: 45

排序

class Solution {
    public int computeArea(int A, int B, int C, int D, int E, int F, int G, int H) {
        int size1 = (C - A) * (D - B);
        int size2 = (G - E) * (H - F);

        if (C <= E || G <= A || H <= B || D <= F)
            return size1 + size2;

        int[] x = new int[]{A, C, E, G};
        int[] y = new int[]{B, D, F, H};
        Arrays.sort(x);
        Arrays.sort(y);
        int size3 = (x[2] - x[1]) * (y[2] - y[1]);

        return size1 + size2 - size3;
    }
}

比较判断

class Solution {
    public int computeArea(int A, int B, int C, int D, int E, int F, int G, int H) {
        int size1 = (C - A) * (D - B);
        int size2 = (G - E) * (H - F);

        if (C <= E || G <= A || H <= B || D <= F)
            return size1 + size2;
        
        int x1 = Math.max(A, E);
        int x2 = Math.min(C, G);
        int y1 = Math.max(B, F);
        int y2 = Math.min(D, H);
        int size3 = (x2 - x1) * (y2 - y1);

        return size1 + size2 - size3;
    }
}

下一个更大元素

给你两个 没有重复元素 的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。
请你找出 nums1 中每个元素在 nums2 中的下一个比其大的值。
nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出 -1 。

示例 1:
输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
输出: [-1,3,-1]
解释:
对于 num1 中的数字 4 ,你无法在第二个数组中找到下一个更大的数字,因此输出 -1 。
对于 num1 中的数字 1 ,第二个数组中数字1右边的下一个较大数字是 3 。
对于 num1 中的数字 2 ,第二个数组中没有下一个更大的数字,因此输出 -1 。

示例 2:
输入: nums1 = [2,4], nums2 = [1,2,3,4].
输出: [3,-1]
解释:
对于 num1 中的数字 2 ,第二个数组中的下一个较大数字是 3 。
对于 num1 中的数字 4 ,第二个数组中没有下一个更大的数字,因此输出 -1 。

单调栈

class Solution {
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        int[] map = new int[10001];
        int len1 = nums1.length, len2 = nums2.length;
        map[nums2[len2 - 1]] = -1;

        Deque<Integer> stack = new LinkedList<>();
        for (int i = 0; i < len2; i++) {
            while (!stack.isEmpty() && stack.peek() < nums2[i]) 
                map[stack.pop()] = nums2[i];
            stack.push(nums2[i]);
        }

        int[] result = new int[len1];
        for (int i = 0; i < len1; i++) 
            result[i] = map[nums1[i]] == 0 ? -1 : map[nums1[i]];
        
        return result;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值