package com.heu.wsq.leetcode.monotone_stack;
import java.util.ArrayDeque;
import java.util.Deque;
/**
* 84. 柱状图中最大的矩形
* @author wsq
* @date 2020/12/26
* 给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
* 求在该柱状图中,能够勾勒出来的矩形的最大面积。
* 由于这道题有图,大家可以访问下方的连接直接去查看
* 以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]。
* 图中阴影部分为所能勾勒出的最大矩形面积,其面积为 10 个单位。
*
* 示例:
* 输入: [2,1,5,6,2,3]
* 输出: 10
*
* 链接:https://leetcode-cn.com/problems/largest-rectangle-in-histogram
*/
public class LargestRectangleArea {
/**
* 暴力解法
* 外侧遍历以每一个矩形高度为底边,然后向左右扩展满足自己条件的宽
* @param heights
* @return
*/
public int largestRectangleArea(int[] heights){
int n = heights.length;
int maxArea = 0;
for (int i = 0; i < n; i++){
int width = 1;
for(int j = i + 1; j < n; j++){
if (heights[j] >= heights[i]){
width++;
}else{
break;
}
}
for (int j = i - 1; j >= 0; j--){
if (heights[j] >= heights[i]){
width++;
}else{
break;
}
}
maxArea = Math.max(width * heights[i], maxArea);
}
return maxArea;
}
/**
* 暴力解法的缺点就是在寻找左右两边"第一个"比当前矩阵低的位置不够效率,时间复杂度为O(n)
* 采用空间换时间的思想,当遇见寻找左右两边 "第一个" 大于或小于 当前元素的元素位置时,我们首先要想到去运用单调栈的思想
* @param heights
* @return
*/
public int largestRectangleArea2(int[] heights){
int n = heights.length;
if (n == 0){
return 0;
}
if (n == 1){
return heights[0];
}
Deque<Integer> stack = new ArrayDeque<>();
int area = 0;
for (int i = 0; i < n; i++){
while (!stack.isEmpty() && heights[stack.peekLast()] > heights[i]){
int height = heights[stack.removeLast()];
int width;
if (stack.isEmpty()){
width = i;
}else{
width = i - stack.peekLast() -1;
}
area = Math.max(area, height * width);
}
stack.addLast(i);
}
while (!stack.isEmpty()){
int height = heights[stack.removeLast()];
int width;
if (stack.isEmpty()){
width = n;
}else{
width = n - stack.peekLast() - 1;
}
area = Math.max(area, width * height);
}
return area;
}
/**
* 哨兵和单调栈通常一起使用,增加虚拟节点,将需要特殊讨论的位置一般化,降低问题的逻辑复杂度,进一步提高算法的效率
* 增加哨兵,降低逻辑的复杂度。
* @param heights
* @return
*/
public int largestRectangleArea3(int[] heights){
int n = heights.length;
if (n == 0){
return 0;
}
if (n == 1){
return heights[0];
}
Deque<Integer> stack = new ArrayDeque<>();
int area = 0;
// 设置哨兵
int[] newHeights = new int[n + 2];
System.arraycopy(heights, 0, newHeights, 1, n);
stack.addLast(newHeights[0]);
for (int i = 1; i < n + 2; i++){
while(newHeights[stack.peekLast()] > newHeights[i]){
int height = newHeights[stack.removeLast()];
int width = i - stack.peekLast() - 1;
area = Math.max(area, height * width);
}
stack.addLast(i);
}
return area;
}
public static void main(String[] args) {
int[] heights = {2, 1, 5, 6, 2, 3};
LargestRectangleArea lr = new LargestRectangleArea();
int ans = lr.largestRectangleArea3(heights);
System.out.println(ans);
}
}
84. 柱状图中最大的矩形(单调栈)
最新推荐文章于 2025-11-24 15:27:16 发布
博客围绕LeetCode,涉及算法和数据结构相关内容,使用Java语言。算法和数据结构是信息技术领域的重要基础,在LeetCode平台上可通过实践提升相关能力。
635

被折叠的 条评论
为什么被折叠?



