【Leetcode】84. 柱状图中最大的矩形

 

 

 暴力解法一:枚举宽度

 1 class Solution {
 2     public int largestRectangleArea(int[] heights) {
 3         int n = heights.length;
 4         int ans = 0;
 5         // 枚举左边界
 6         for (int left = 0; left < n; ++left) {
 7             int minHeight = Integer.MAX_VALUE;
 8             // 枚举右边界
 9             for (int right = left; right < n; ++right) {
10                 // 确定高度
11                 minHeight = Math.min(minHeight, heights[right]);
12                 // 计算面积
13                 ans = Math.max(ans, (right - left + 1) * minHeight);
14             }
15         }
16         return ans;
17     }
18 }

暴力解法二:枚举高度

 1 class Solution {
 2     public int largestRectangleArea(int[] heights) {
 3         int n = heights.length;
 4         int ans = 0;
 5         for(int mid = 0; mid < n; mid++){
 6             int left = mid;
 7             int right = mid;
 8             int height = heights[mid];
 9             while(left-1 >= 0 && heights[left-1] >= height){
10                 left--;
11             }
12             while(right+1 < n && heights[right+1] >= height){
13                 right++;
14             }
15             ans = Math.max((right-left+1)*height,ans);
16         }
17         return ans;
18     }
19 }

枚举高度的思路和单调栈结构是一样的,找到当前数字左右两边距离最近的比它小的值的位置。

单调栈的实现思路:始终保持一个栈的单调性,如果入栈元素A试图破坏单调性,栈顶元素X出栈,

我们可以获得X的两边小值的信息,让X出栈的入栈元素A就是X右边最近的小值,X出栈之后的栈顶元素B就是X左边最近的小值。

如果X弹出后入栈元素A还是破坏单调性,则继续弹出,重复上述过程;

如果不破坏单调性,A入栈。

遍历完数组之后,栈不空,依次弹出栈,且这些元素的右边没有比它小的值,左边比它小的值是弹出后的栈顶元素。

这道题是找左右两边较小的值,所以从栈顶到栈底是单调递减的

如果是找左右边较大的值,栈顶到栈底就该是单调递增的。

 

使用单调栈来解:

在单调栈中,如果左边和右边有没有比当前值小的返回(-1,-1)

在这里使用单调栈的关键就是弄清楚没有找到较小值的时候left和right的值怎么设置

当左边没有较小值的时候,说明从cur位置可以一直延申到0位置

当右边没有较小值的时候,说明从cur位置可以一直延申到数组末尾位置

 1 class Solution {
 2     public int largestRectangleArea(int[] heights) {
 3         int n = heights.length;
 4         Stack<Integer> stack = new Stack<>();
 5         int ans = 0;
 6         //栈顶元素较大
 7         for(int i = 0; i < n; i++){
 8             while(!stack.isEmpty() && heights[stack.peek()]>heights[i]){
 9                 int cur = stack.pop();
10                 int right = i;
11                 int left = stack.isEmpty()?-1:stack.peek();
12                 System.out.println(left+" "+cur+" "+right);
13                 ans = Math.max(ans, (right-left-1)*heights[cur]);
14             }
15             stack.push(i);
16         }
17         while(!stack.isEmpty()){
18             int cur = stack.pop();
19             int right = heights.length;
20             int left = stack.isEmpty()?-1:stack.peek();
21             System.out.println(left+" "+cur+" "+right);
22             if(right == cur && left == -1){
23                 ans = Math.max(ans, heights[cur]);
24             }
25             ans = Math.max(ans, (right-left-1)*heights[cur]);
26         }
27         return ans;
28     }
29 }

 

posted @ 2020-05-30 22:19  xd会飞的猫  阅读(186)  评论(0编辑  收藏  举报