刷题-最大矩形面积-动态规划和单调栈实现

82 阅读1分钟

题目连接

leetcode:leetcode.cn/problems/la…

稀土掘金:www.marscode.cn/practice/8e…

题目

截屏2025-01-06 下午11.34.09.png

解法一:动态规划

定义 dp[i][j] 表示从 i 到 j 的最小值, 即柱子的最小高度。

初始可知道:dp[i][i] = array[i]

dp的状态转移方程为:dp[i][j] = min(dp[i][j-1],dp[j][j]),且j > i;

位置i到j的面积为:area = dp[i][j] * (j-i + 1)

最后,双层for循环dp,取最大 maxArea 返回。

该解法时间复杂度为:O(n^2)


public class Main {
    public static int min(int a, int b) {
        if (a > b) {
            return b;
        }
        return a;
    }

    public static int solution(int n, int[] array) {
        int len = array.length;
        int[][] dp = new int[len][len];

        for (int i = 0; i < len; i++) {
            dp[i][i] = array[i];
            for (int j = i + 1; j < len; j++) {
                dp[i][j] = min(dp[i][j - 1], array[j]);
            }

        }

        int res = 0;
        for (int i = 0; i < len; i++) {
            for (int j = i; j < len; j++) {
                int s = (j - i + 1) * dp[i][j];
                if (res < s) {
                    res = s;
                }
            }

        }

        return res;
    }

    public static void main(String[] args) {
        System.out.println(solution(5, new int[] { 1, 2, 3, 4, 5 }) == 9);
    }
}

解法二:单调栈

初始将第一个数据压入栈内,遍历后面的数据,

遍历每一个数据,和栈顶元素进行对比:

  • 如果大于等于栈顶元素,将遍历的当前数据押入栈内。
  • 如果小于栈顶元素,弹出栈顶元素作为矩形的高度。计算面积。

时间复杂度:O(n)

public int largestRectangleArea(int[] heights) {
        List<Integer> hs = new ArrayList<>();
        for (int i = 0; i < heights.length; i++) {
            hs.add(heights[i]);
        }
        hs.add(0); // 添加0用于处理边界问题。

        Stack<Integer> stack = new Stack<>();
        stack.add(-1); // 添加-1用于处理边界问题,防止出现越界情况
        stack.add(0);

        int maxArea = 0;
        for (int i = 1; i < hs.size(); i++) {
            int cur = hs.get(i);
            while (true) {
                int stackTopNumIndex = stack.get(stack.size() - 1);
                if (stackTopNumIndex == -1 || hs.get(stackTopNumIndex) <= cur) {
                    stack.add(i);
                    break;
                } else {
                    stack.pop();
                    int stackTopNumIndex_2 = stack.get(stack.size() - 1);
                    int weight = (i - stackTopNumIndex) + (stackTopNumIndex - stackTopNumIndex_2) - 1;
                    int area = weight * hs.get(stackTopNumIndex);
                    if (maxArea < area) {
                        maxArea = area;
                    }
                }
            }
        }
        return maxArea;
    }