「这是我参与2022首次更文挑战的第9天,活动详情查看:2022首次更文挑战」。
题目
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
示例1
输入:heights = [2,1,5,6,2,3]
输出:10
解释:最大的矩形为图中红色区域,面积为 10
示例2
输入: heights = [2,4]
输出: 4
思路
题目求的是一个最大的矩形面积,而面积的计算公式为 height * width
,容易想到的是,如果能够固定一个值,比如 height
,尝试把 width
增加,就会得到越来越大的矩形。
但是这道题会有一个问题,且存在随着高度 height
的减小,宽度 width
会增加的问题,面积的大小会存在不确定性。
换个思路: 如果不能确定 height、width
,那确定一个边界试试?比如确定左边界,然后枚举右边界,计算过程中的面积最大值;暴力解法就有了~
暴力解法完整代码
/**
* @param {number[]} heights
* @return {number}
*/
var largestRectangleArea = function (heights) {
const n = heights.length;
let maxArea = 0;
// 枚举左边界
for(let i = 0; i < n; i++) {
// 先定义最小高度为最大值
let minHeight = Number.MAX_VALUE;
// 枚举右边界
for(let j = i; j < n; j++) {
// 如果右边界高度为0,与之前的块 无法形成 矩形,可以退出右边界枚举
if(heights[j] == 0) {
break;
}
// 过程中的最小高
minHeight = Math.min(minHeight, heights[j]);
// 比较面积
maxArea = Math.max(maxArea, minHeight * (j - i + 1));
}
}
return maxArea;
};
暴力解法的时间复杂度,为 O(n ^ 2)
,依旧没有通过 LeetCode
的提交测试,😅~~
官方解法:单调栈
等待更新:😭(看努力看懂中)
const largestRectangleArea = (heights) => {
let maxArea = 0
const stack = []
heights = [0, ...heights, 0]
for (let i = 0; i < heights.length; i++) {
while (heights[i] < heights[stack[stack.length - 1]]) { // 当前bar比栈顶bar矮
const stackTopIndex = stack.pop() // 栈顶元素出栈,并保存栈顶bar的索引
maxArea = Math.max( // 计算面积,并挑战最大面积
maxArea, // 计算出栈的bar形成的长方形面积
heights[stackTopIndex] * (i - stack[stack.length - 1] - 1)
)
}
stack.push(i) // 当前bar比栈顶bar高了,入栈
}
return maxArea
}
小结
暴力解法一般是最普通的思路,依据的是最常见的公示、常理之类的,通过把所有可能的答案都举例出来,然后找出最符合题目要求的那一个
但是往往暴力解法的时间复杂度很高,需要优化很多不必要的计算或者依据一些结论取巧,技巧性往往很高!
如果没有得出更优化的解法,说明算法题做的还不够多!
LeetCode 👉 HOT 100 👉 柱状图中最大的矩形 - 中等题 ✅
合集:LeetCode 👉 HOT 100,有空就会更新,大家多多支持,点个赞👍
如果大家有好的解法,或者发现本文理解不对的地方,欢迎留言评论 😄