【单调栈】子数组的最小值之和


import java.util.Deque;
import java.util.LinkedList;

/** 参考链接:https://leetcode.cn/problems/sum-of-subarray-minimums/solutions/1930857/gong-xian-fa-dan-diao-zhan-san-chong-shi-gxa5/
 *           https://leetcode.cn/problems/sum-of-subarray-minimums/solutions/1931139/-by-muse-77-367z/
 * 单调栈
 *  思路:将求取每个连续的子数组的最小值之和,转换为求:以每个数为最小值然后求以该数
 *        为最小值子数组的个数,然后个数乘以该最小值得到的数加到结果集中。重复这样的
 *        操作遍历全部的数。
 *
 *  问题:如何找到以该数为最小值的数组个数。
 *  想要解决这个问题,需要明白 乘法原理: 最小值左边的数乘以右边的数等于该数全部的连续子序列的个数
 *
 *       栈中存储的全部是下标,但数值是从栈底到栈顶是单调递增的。
 *
 *
 * @auther start
 * @create 2023-11-26 21:35
 */
public class L907 {

    private static final long MOD = (long) 1e9 + 7;
    public int sumSubarrayMins(int[] arr) {
        long ans = 0;
        Deque<Integer> st = new LinkedList<>();
        st.push(-1);
        for (int r = 0; r <= arr.length; r++) {
            int x = r < arr.length ? arr[r] : -1;
            // x 小于栈顶元素,栈顶元素出栈,新的栈顶元素是该元素的
            // 左边界,r是该元素的有边界。
            while (st.size() > 1 && arr[st.peek()] >= x) {
                int i = st.pop();
                //将该最小值组成的元素个数乘以该最小值的结果添加到结果集中。
                ans += (long) arr[i] * (i - st.peek()) * (r - i);
            }
            st.push(r);
        }
        //输出结果
        return (int) (ans % MOD);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值