84. 柱状图中最大的矩形
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
示例 1:
输入:heights = [2,1,5,6,2,3]
输出:10
解释:最大的矩形为图中红色区域,面积为 10
示例 2:
输入: heights = [2,4]
输出: 4
提示:
1 <= heights.length <=10^5
0 <= heights[i] <= 10^4
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
  | 
class Solution {
    public int largestRectangleArea(int[] heights) {
        int n=heights.length;
        int []ph=new int [n+2];
        int ans=0;
        for(int i=1;i<n+1;i++) ph[i]=heights[i-1];
        Deque<Integer> stack=new ArrayDeque<>();
        for(int i=0;i<n+2;i++){
          //  System.out.println(i+" "+stack);
            while(!stack.isEmpty()&&ph[stack.getLast()]>ph[i]){
               
                int cur=stack.removeLast();
                ans=Math.max(ans,(i-stack.getLast()-1)*ph[cur]);
            }
            stack.offer(i);
        }
        return ans;
    }
}
  | 
 
这一题是干嘛呢?找到i左边和右边小于它的第一个数,中间就是最大面积了。
方法是单调栈。
注意栈里面记录的是下标。
在Java中使用的是ArrayDeque数据结构。
所以我建议看到有类似最右最左边找最小的数,优先来看看84是如何实现单调栈的。
我们每次弹出的时候做计算!!
为了加深印象,遂添加cpp题解
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  | 
class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int n=heights.size();
        vector<int> v(n+2);
        for(int i=0;i<n;i++){
            v[i+1]=heights[i];
        }
        stack<int> s;
        int ans=0;
        for(int i=0;i<n+2;i++){
            while(!s.empty()&&v[s.top()]>v[i]){
                int cur=s.top();
                s.pop();
                ans=max(ans,v[cur]*(i-s.top()-1));
            }
            s.push(i);
            
        }
        return ans;
    }
};
  | 
 
难度中等402
给定一个整数数组 arr,找到 min(b) 的总和,其中 b 的范围为 arr 的每个(连续)子数组。
由于答案可能很大,因此 返回答案模 10^9 + 7 。
示例 1:
1
2
3
4
5
  | 
输入:arr = [3,1,2,4]
输出:17
解释:
子数组为 [3],[1],[2],[4],[3,1],[1,2],[2,4],[3,1,2],[1,2,4],[3,1,2,4]。 
最小值为 3,1,2,4,1,1,2,1,1,1,和为 17。
  | 
 
示例 2:
1
2
  | 
输入:arr = [11,81,94,43,3]
输出:444
  | 
 
提示:
1 <= arr.length <= 3 * 104 
1 <= arr[i] <= 3 * 104 
通过次数20,094
提交次数58,149
注意也是在弹出栈的时候做计算
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  | 
class Solution {
public:
    int sumSubarrayMins(vector<int>& arr) {
        int n=arr.size();
        vector<int> v(n+2);
        for(int i=0;i<n;i++){
            v[i+1]=arr[i];
        }
        stack<int> s;
        int MOD=1000000007;
        long ans=0;
        for(int i=0;i<n+2;i++){
            while(!s.empty()&&v[s.top()]>v[i]){
                int cur=s.top();
                s.pop();
               // printf("left:%d,mid=%d right%d,\n",s.top(),(cur),(i));
                ans+=1l*(i-cur)%MOD*(cur-s.top())%MOD*v[cur];
                ans%=MOD;
            }
            s.push(i);
        }
        return (int)ans%MOD;
    }
};
  |