LeetCode-907. 子数组的最小值之和【单调栈,数组】

LeetCode-907. 子数组的最小值之和【单调栈,数组】

  • 题目描述:
  • 解题思路一:单调栈。我们计算每个以arr[i]为最小值的连续子数组的个数num。然后num×arr[i]便是答案。
  • 解题思路二:
  • 解题思路三:

题目描述:

给定一个整数数组 arr,找到 min(b) 的总和,其中 b 的范围为 arr 的每个(连续)子数组。

由于答案可能很大,因此 返回答案模 10^9 + 7 。

示例 1:

输入: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:

输入:arr = [11,81,94,43,3]
输出:444

提示:

1 <= arr.length <= 3 * 10^4
1 <= arr[i] <= 3 * 10^4
该题力扣
注意是连续的子数组,不是随意取的!

解题思路一:单调栈。我们计算每个以arr[i]为最小值的连续子数组的个数num。然后num×arr[i]便是答案。

LeetCode-907. 子数组的最小值之和【单调栈,数组】_第1张图片

首先,维护一个单调栈,每次计算栈顶的答案。即arr[i]<=arr[stk.top()]时计算,此时的此时遍历到的元素小于等于栈顶元素,而栈顶元素必然小于上一个栈内元素,故可以计算以当前栈顶元素为最小值的连续子数组的个数num,然后乘以栈顶元素。

class Solution {
public:
    const int MOD=1e9+7;
    int sumSubarrayMins(vector<int>& arr) {
        stack<int> stk;
        arr.push_back(0);//因为arr[i]>=1,最后加一个最小的元素可以保证栈中所有元素都会被弹出计算。之后stk为空,所以0不会参与计算
        long ans=0;
        for(int i=0;i<arr.size();++i){
            while(!stk.empty()&&arr[i]<=arr[stk.top()]){//保证栈内元素是递增的
                int index=stk.top();stk.pop();
                int prev_index=-1;
                if(!stk.empty()) prev_index=stk.top();//若栈为空上一个小元素取-1,否则取stk.top()
                int prev_count=index-prev_index-1;//数量m
                int next_count=i-index-1;//数量n
                ans+=long(arr[index])*(prev_count+1)*(next_count+1)%MOD;
                ans%=MOD;
            }
            stk.push(i);
        }
        return ans;
    }
};

时间复杂度:O(n)
空间复杂度:O(n)

解题思路二:


解题思路三:


参考链接

你可能感兴趣的:(算法题,leetcode,c++,数据结构,算法,单调栈)