[LeetCode]84. 柱状图中最大的矩形

题目

84. 柱状图中最大的矩形

84. 柱状图中最大的矩形
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。

求在该柱状图中,能够勾勒出来的矩形的最大面积。

 

示例 1:



输入:heights = [2,1,5,6,2,3]
输出:10
解释:最大的矩形为图中红色区域,面积为 10
示例 2:



输入: heights = [2,4]
输出: 4
 

提示:

1 <= heights.length <=105
0 <= heights[i] <= 104

解法

方法1:单调栈+哨兵

public int largestRectangleArea(int[] heights) {
    int n = heights.length;
    int[] nums = new int[n + 2];
    System.arraycopy(heights, 0, nums, 1, heights.length);
    Deque<Integer> stk = new ArrayDeque<>();
    int maxArea = 0;
    for (int i = 0; i < nums.length; i++) {
        //当前的柱子的高度比栈顶的柱子的高度低,计算以弹出的栈顶高度的柱子为高的矩形面积
        while (!stk.isEmpty() && nums[stk.peek()] > nums[i]) {
            int h = nums[stk.pop()];
            maxArea = Math.max(maxArea, h * (i - stk.peek() - 1));
        }
        stk.push(i);
    }
    return maxArea;
}
        public int largestRectangleArea(int[] heights) {
            Deque<Integer> stk = new ArrayDeque<>();
            //设置哨兵
            stk.push(-1);
            int maxArea = 0;
            for (int i = 0; i < heights.length; i++) {
                while (stk.peek() != -1 && heights[i] < heights[stk.peek()]) {
                    int h = heights[stk.pop()];
                    maxArea = Math.max(maxArea, h * (i - stk.peek() - 1));
                }
                stk.push(i);
            }
            //[2,4]case
            //如果栈内还存在合法的下标没有出栈,则以数组的右边界为界限计算最大区域
            while (stk.peek() != -1) {
                int h = heights[stk.pop()];
                maxArea = Math.max(maxArea, h * (heights.length - stk.peek() - 1));
            }
            return maxArea;
        }
public int largestRectangleArea(int[] heights) {
    Deque<Integer> stk = new ArrayDeque<>();
    //最末尾数设置为0,此前的柱子的高度都会比这个高
    int[] nums = new int[heights.length + 1];
    for (int i = 0; i < heights.length; i++) nums[i] = heights[i];
    int maxArea = 0;
    for (int i = 0; i < nums.length; i++) {
        while (!stk.isEmpty() && nums[stk.peek()] > nums[i]) {
            int h = nums[stk.pop()];
            //如果栈空了,就以当前的下标索引为宽度 即 i -0 数组的左边界
            maxArea = Math.max(maxArea, h * (stk.isEmpty() ? i : i - stk.peek() - 1));
        }
        stk.push(i);
    }
    return maxArea;
}

方法2:双指针

  • TLE
        public int largestRectangleArea(int[] heights) {
            int maxArea = 0;
            int n = heights.length;
            int[] nums = new int[n + 2];
            for (int i = 0; i < n; i++) {
                nums[i + 1] = heights[i];
            }
            for (int i = 1; i < nums.length - 1; i++) {
                int l = i, r = i;
                while (l >= 0 && nums[l] >= nums[i]) l--;
                while (r < nums.length && nums[r] >= nums[i]) r++;
                maxArea = Math.max(maxArea, nums[i] * (r - l - 1));
            }
            return maxArea;
        }

方法3:计算左右索引

  • 类似1856、907等题的做法
        public int largestRectangleArea(int[] heights) {
            int n = heights.length;
            int[] left = new int[n];
            int[] right = new int[n];
            // 记录左边第一个小于等于该柱子的下标
            left[0] = -1;
            for (int i = 1; i < n; i++) {
                int t = i - 1;
                while (t >= 0 && heights[t] >= heights[i]) t = left[t];
                left[i] = t;
            }
            // 记录每个柱子 右边第一个小于等于该柱子的下标
            right[n - 1] = n;
            for (int i = n - 2; i >= 0; i--) {
                int t = i + 1;
                while (t < n && heights[t] >= heights[i]) t = right[t];
                right[i] = t;
            }
            // 计算
            int maxArea = 0;
            for (int i = 0; i < n; i++) {
                int t = heights[i] * (right[i] - left[i] - 1);
                maxArea = Math.max(t, maxArea);
            }
            return maxArea;
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值