LeetCode 907. 子数组的最小值之和***(double)

具体思路:

dp超时,整体思路为左右拓展思路;

如果枚举每个值,向两个方向搜索,则必定会得到一个区间,使得该区间内以该值中心元素最小;

所以只需要按照该思路进行枚举即可,但是可惜会超时;

所以采用单调栈;

维护一个递增栈,栈内存放索引,当一个元素小于栈顶元素,则进行弹栈;

但是这里很多题解都没说明白,弹栈并不是计算该元素的左右区间,而是计算栈内节点的左右区间;

例如:3,4,5,1序列;

如果遍历到元素1,则说明3,4,5的右边界都为1;

此时,比较难的是左边的确定,即为什么左边界就是自己的栈内的下一个元素;

因为是单调递增栈,所以栈内每个元素都比下一位元素要大,因此,左边界可以确定;

并且每次算完之后,都会把计算后的元素弹栈,为新入栈的元素做好左边界准备;

例如:0,3,4,5,1;

1入栈后,栈内坐标必定为0,4;

当出现比1小的元素,会对1进行判断,所以左边界直接就是4-0=left;

具体代码:

using ll=long long;
class Solution {
public:
    int sumSubarrayMins(vector<int>& arr) {
        stack<int>st;
        ll mod=pow(10,9)+7;
        ll ret=0;
        arr.push_back(-1);
        for(int i=0;i<arr.size();i++){
            while(!st.empty()&&arr[st.top()]>=arr[i]){
                int index=st.top();
                st.pop();
                int right=i-index;
                int l=st.empty()?-1:st.top();
                int left=index-l;
                ll temp=left*right*ll(arr[index])%mod;
                ret+=temp%mod;
                ret%=mod;
            }
            st.push(i);
        }
        return ret;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值