• 【Leetcode每日一题:907.子数组的最小值之和~~~单调栈】


    题目描述

    给定一个整数数组 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 * 104
    1 <= arr[i] <= 3 * 104

    解题思路

    1. 这是一道通过单调栈来解决的问题,题目要求我们求得一个数组中所有子数组中的最小值,然后求得它的累加和。
    2. 我们的求解思路是以每一个数作为当前子数组中的最小值,然后找寻左边比自身位置小的元素下标,同理,右边也是,找到比它还小的位置元素的下标。通过元素下标的位置,根据乘法原理求得对当前有多少子数组是以当前位置作为最小值的结果,贡献就是:当前位置的元素*个数。
    3. 解决找到某一个数右边比它大,或者小,左边比它大,或者小,最快的解决方式就是单调栈。

    实现代码

    class Solution {
        private static final long MOD = (long) 1e9 + 7;
    
        public int sumSubarrayMins(int[] arr) {
            int n = arr.length;
            int[] left = new int[n];
            int[] right = new int[n];
            Arrays.fill(right, n);
            Deque<Integer> st = new ArrayDeque<Integer>();
            st.push(-1); 
            for (int i = 0; i < n; ++i) {
                //寻找右边小于当前位置第一个元素
                while (st.size() > 1 && arr[st.peek()] >= arr[i])
                    right[st.pop()] = i; 
                left[i] = st.peek();
                st.push(i);
            }
            long ans = 0L;
            for (int i = 0; i < n; ++i)
                //乘法原理计算结果
                ans += (long) arr[i] * (i - left[i]) * (right[i] - i); 
            return (int) (ans % MOD);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    运行结果

    在这里插入图片描述

  • 相关阅读:
    设计模式简介
    zabbix配置触发器
    学生信息管理系统(Python)完整版
    【二:Spring-AOP】
    百度文库旋转验证码识别
    外贸怎么在谷歌搜索客户?
    缓存 (模拟两种:数据库提供数据到缓存、外界提供数据到缓存)
    制作一个模板二
    基于VC的WinSock网络编程实用宝典
    JWT在spring boot中的应用
  • 原文地址:https://blog.csdn.net/Coder_ljw/article/details/127565055