chencl1986 / Blog

Welcome to lee's blog.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

LeetCode题解:84. 柱状图中最大的矩形,使用栈,JavaScript,详细注释

chencl1986 opened this issue · comments

原题链接:https://leetcode-cn.com/problems/largest-rectangle-in-histogram/

解题思路:

参考了官方题解中的方法二:单调栈 + 常数优化。

  1. 将元素入栈,当遇到待入栈元素小于栈顶时,就将栈中元素依次弹出,直到栈顶比入栈元素小为止。
  2. 通过第一步的操作,就保证了栈是有小到大排序。
  3. 当入栈元素比栈顶小时,入栈元素即为右边界,栈顶为高,栈顶的下一个元素为左边界,即可计算面积。
  4. 当所有元素都完成入栈操作后,如果栈中还有元素,则需要以此将栈中元素依次弹出计算面积。
  5. 在清空栈之前,栈顶为heights的最后一个元素,且栈是有小到大排序,因此栈中元素的右边界都为heights.length
/**
 * @param {number[]} heights
 * @return {number}
 */
var largestRectangleArea = function (heights) {
  let area = 0; // 存储最大面积
  let stack = [-1]; // 用栈从低到高排列元素,保证栈内高度元素只剩1个时,能够正确计算宽度

  for (let i = 0; i < heights.length; i++) {
    // 当遇到比栈顶元素小的值时,表示查找到了栈顶元素对应的右边界,需要将栈顶元素弹出计算面积
    while (heights[i] < heights[stack[stack.length - 1]]) {
      const pop = stack.pop(); // 当前高度的index
      const left = stack[stack.length - 1]; // 栈顶元素为当前高度的左边界
      const width = i - left - 1; // i为右边界,宽度为左右边界之差减1
      area = Math.max(area, heights[pop] * width); // 取当前的最大面积
    }
    // 将当前值存入栈。
    // 需要注意,如果所有高度都按照while循环的规则得到处理,此时的栈还有一个值为-1,push之后还剩2个值,即-1和heights的最后一个元素。
    stack.push(i);
  }

    // 如果栈未被清空,则表示还需要继续清空栈,当前栈顶为heights中的最后一个元素,且栈是有小到大排序。也就是说栈内所有元素的右边界都在heights.length。
  while (stack.length > 1) {
    const pop = stack.pop(); // 当前高度的index
    const left = stack[stack.length - 1]; // 栈顶元素为当前高度的左边界
    const width = heights.length - left - 1; // heights.length为右边界。
    area = Math.max(area, heights[pop] * width); // 取当前的最大面积
  }

  return area;
};