LeetCode热题(JS版) - 84. 柱状图中最大的矩形

818 阅读3分钟

题目

给定一个非负整数数组 heights,表示一个柱状图中各个柱子的高度。每个柱子的宽度为1。找到柱状图中面积最大的矩形。

示例

image.png

输入: [2,1,5,6,2,3] 
输出: 10 
解释: 上图所示的矩形即为面积最大的矩形,其面积为2x5 = 10

思路:单调栈

  • 首先,我们遍历每个柱子,并维护一个递增的栈。
  • 对于每个柱子,如果当前高度大于栈顶元素的高度,我们将其入栈。
  • 否则,我们从栈中不断弹出元素,直到栈顶元素小于当前柱子的高度。
  • 在这个过程中,我们计算以弹出元素为高度的矩形的面积,并更新最大面积。

代码实现

function largestRectangleArea(heights: number[]): number {
  const stack: number[] = []; // 创建一个空栈,用于存储数组索引
  let maxArea = 0; // 初始化最大面积为0

  for (let i = 0; i <= heights.length; i++) { // 遍历数组,包括最后一个虚拟索引
    while (stack.length > 0 && (i === heights.length || heights[i] < heights[stack[stack.length - 1]])) {
      // 当栈不为空且当前高度小于栈顶元素对应的高度时执行循环
      const heightIndex = stack.pop()!; // 弹出栈顶元素的索引
      const height = heights[heightIndex]; // 获取栈顶元素对应的高度
      
      // 计算矩形的宽度
      const width = stack.length === 0 ? i : i - stack[stack.length - 1] - 1;
      // 更新最大面积
      maxArea = Math.max(maxArea, height * width);
    }
    stack.push(i); // 将当前索引入栈
  }

  return maxArea; // 返回最大面积
}

解释下:

  1. 首先,创建一个空栈stack和初始最大面积maxArea为0。

  2. 开始遍历数组:

    • i = 0时,将索引0入栈。此时栈中的元素为[0]。

    • i = 1时,由于当前元素1小于栈顶元素2,进入while循环,弹出栈顶元素2并计算矩形面积。

      • 弹出栈顶元素2,得到栈中的元素为[0]。
      • 计算矩形宽度:width = i - stack[stack.length - 1] - 1 = 1 - 0 - 1 = 0
      • 更新最大面积:maxArea = Math.max(maxArea, height * width) = Math.max(0, 2 * 0) = 0
    • 将索引1入栈。此时栈中的元素为[0, 1]。

    • i = 2时,由于当前元素5大于栈顶元素1,直接将索引2入栈。此时栈中的元素为[0, 1, 2]。

    • i = 3时,由于当前元素6大于栈顶元素5,直接将索引3入栈。此时栈中的元素为[0, 1, 2, 3]。

    • i = 4时,由于当前元素2小于栈顶元素6,进入while循环,弹出栈顶元素3并计算矩形面积。

      • 弹出栈顶元素3,得到栈中的元素为[0, 1, 2]。
      • 计算矩形宽度:width = i - stack[stack.length - 1] - 1 = 4 - 2 - 1 = 1
      • 更新最大面积:maxArea = Math.max(maxArea, height * width) = Math.max(0, 6 * 1) = 6
    • 继续进入while循环,弹出栈顶元素2并计算矩形面积。

      • 弹出栈顶元素2,得到栈中的元素为[0, 1]。
      • 计算矩形宽度:width = i - stack[stack.length - 1] - 1 = 4 - 1 - 1 = 2
      • 更新最大面积:maxArea = Math.max(maxArea, height * width) = Math.max(6, 5 * 2) = 10
    • 将索引4入栈。此时栈中的元素为[0, 1, 4]。

    • i = 5时,由于已经遍历完数组,进入while循环,弹出栈顶元素4并计算矩形面积。

      • 弹出栈顶元素4,得到栈中的元素为[0, 1]。
      • 计算矩形宽度:width = i - stack[stack.length - 1] - 1 = 5 - 1 - 1 = 3
      • 更新最大面积:maxArea = Math.max(maxArea, height * width) = Math.max(10, 2 * 3) = 10
  3. 最终得到最大矩形面积为10,即函数返回值为10。

复杂度分析

  • 时间复杂度:O(N),其中 N 表示柱状图的长度。我们只需要遍历一次柱状图中的每个元素,并且每个元素最多入栈一次和出栈一次。
  • 空间复杂度:O(N),使用了一个栈来存储柱子的索引,栈中的元素数量不会超过柱状图的长度。