豆包MarsCode AI刷题(二)

56 阅读5分钟

今天给大家分享一下每日刷题的题目解析和经验分享,本系列预计会推出五期,今天给大家带来的是第二期的分享。

最大矩形面积问题


问题描述

小S最近在分析一个数组h1,h2,...,hNh_1,h_2,...,h_N数组的每个元素代表某种高度。小S对这些高度感兴趣的是,当我们选取任意 kk 个相邻元素时,如何计算它们所能形成的最大矩形面积。

对于 kk个相邻的元素,我们定义其矩形的最大面积为:

R(k)=k×min(h[i],h[i+1],...,h[i+k1])R(k)=k×min(h[i],h[i+1],...,h[i+k1])R(k)=k×min(h[i],h[i+1],...,h[i+k−1])R(k)=k×min(h[i],h[i+1],...,h[i+k−1])

即,R(k)R(k) 的值为这 kk 个相邻元素中的最小值乘以 kk。现在,小S希望你能帮他找出对于任意 kR(k)k,R(k) 的最大值。


测试样例

样例 1:

输入:n = 5, array = [1, 2, 3, 4, 5]
输出:9

样例 2:

输入:n = 6, array = [5, 4, 3, 2, 1, 6]
输出:9

样例 3:

输入:n = 4, array = [4, 4, 4, 4]
输出:16

解题方法1——暴力求解

public static int solution(int n, int[] array) {
        int maxArea = 0;
        // 遍历所有可能的 k 值
        for (int k = 1; k <= n; k++) {
            // 遍历数组,计算以每个元素为起点的 k 个相邻元素的最小值
            for (int i = 0; i <= n - k; i++) {
                int minHeight = array[i];
                // 计算 k 个相邻元素的最小值
                for (int j = 1; j < k; j++) {
                    if (array[i + j] < minHeight) {
                        minHeight = array[i + j];
                    }
                }
                // 计算面积并更新最大面积
                int area = k * minHeight;
                if (area > maxArea) {
                    maxArea = area;
                }
            }
        }
        return maxArea;
    }

解题思路

  1. 遍历所有可能的 k 值

    • 外层循环从 k = 1 到 k = n,遍历所有可能的 k 值。k 表示选取的相邻元素的个数。
  2. 遍历数组,计算以每个元素为起点的 k 个相邻元素的最小值

    • 对于每个 k 值,内层循环从 i = 0 到 i = n - k,遍历数组,计算以每个元素为起点的 k 个相邻元素的最小值。
  3. 计算 k 个相邻元素的最小值

    • 对于每个起点 i,使用一个内层循环从 j = 1 到 j = k - 1,计算 k 个相邻元素的最小值。
  4. 计算面积并更新最大面积

    • 计算面积 area = k * minHeight,其中 minHeight 是 k 个相邻元素的最小值。
    • 如果计算的面积 area 大于当前的最大面积 maxArea,则更新 maxArea
  5. 返回最大面积

    • 最终返回 maxArea,即所有可能的 k 值中最大的矩形面积。

复杂度分析


时间复杂度

暴力求解代码使用了三重循环来计算最大矩形面积:

  1. 外层循环遍历所有可能的 (k) 值,从 1 到 (n)。
  2. 中层循环遍历数组,计算以每个元素为起点的 (k) 个相邻元素的最小值。
  3. 内层循环计算 (k) 个相邻元素的最小值。
  • 外层循环执行 (n) 次。
  • 中层循环执行 (n - k + 1) 次。
  • 内层循环执行 (k - 1) 次。

因此,总的时间复杂度为 (O(n^3))。

空间复杂度

当前代码的空间复杂度主要由以下部分组成:

  1. 输入数组 array,占用 (O(n)) 的空间。
  2. 其他变量(如 maxAreaminHeightarea 等),占用常数空间 (O(1))。

因此,总的空间复杂度为 (O(n))。

算法优化

  1. 单调栈:单调栈是一种常用的数据结构,用于在 (O(n)) 时间内解决与区间最小值相关的问题。我们可以使用单调栈来维护一个递增的栈,栈中存储的是数组元素的索引。

  2. 计算最大矩形面积:通过单调栈,我们可以快速计算出以每个元素为最小值的最大矩形面积。具体步骤如下:

    • 遍历数组,对于每个元素,如果栈顶元素的高度小于当前元素的高度,则将当前元素的索引入栈。
    • 如果栈顶元素的高度大于等于当前元素的高度,则弹出栈顶元素,并计算以栈顶元素为最小值的最大矩形面积。
    • 计算面积时,宽度为当前元素的索引与栈顶元素的索引之差。
  3. 边界处理:在遍历结束后,栈中可能还有元素,我们需要继续处理这些元素,直到栈为空。

public static int solution(int n, int[] array) {
        int maxArea = 0;
        Stack<Integer> stack = new Stack<>();
        
        // 遍历数组
        for (int i = 0; i <= n; i++) {
            int h = (i == n) ? 0 : array[i];
            
            // 如果栈不为空且当前高度小于栈顶元素对应的高度
            while (!stack.isEmpty() && h < array[stack.peek()]) {
                int height = array[stack.pop()];
                int width = stack.isEmpty() ? i : i - stack.peek() - 1;
                // 计算面积并更新最大面积
                int area = height * width;
                if (area > maxArea) {
                    maxArea = area;
                }
            }
            
            // 将当前索引入栈
            stack.push(i);
        }
        
        return maxArea;
    }

复杂度分析


时间复杂度

当前代码使用了单调栈来计算最大矩形面积,具体步骤如下:

  1. 遍历数组:外层循环遍历数组中的每个元素,时间复杂度为 (O(n))。
  2. 单调栈操作:在每次遍历中,单调栈的操作(入栈和出栈)最多执行 (O(n)) 次。
  • 外层循环执行 (n + 1) 次(包括最后一个虚拟元素)。
  • 单调栈操作(入栈和出栈)最多执行 (2n) 次(每个元素最多入栈和出栈一次)。

因此,总的时间复杂度为 (O(n))。

空间复杂度

当前代码的空间复杂度主要由以下部分组成:

  1. 输入数组 array,占用 (O(n)) 的空间。
  2. 单调栈 stack,最多存储 (n) 个元素,占用 (O(n)) 的空间。
  3. 其他变量(如 maxAreahheightwidtharea 等) ,占用常数空间 (O(1))。

因此,总的空间复杂度为 (O(n))。