码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 【LeetCode】Day169-子数组的最小值之和


    题目

    907. 子数组的最小值之和【中等】

    题解

    单调栈

    left[i]:以arr[i]元素为最右且最小的子序列数目
    right[i]:以arr[i]元素为最左且最小的子序列数目

    对于每一个arr[i],

    • 求左边第一个从左向右遍历数组,维护单调递增的栈。
      如果栈顶元素>当前元素arr[i],则将其弹出,直到栈顶元素 栈顶元素即为左边第一个left[i]=i-j
    • 求右边第一个>=arr[i]的元素:从右向左遍历数组,维护单调递增的栈。
      如果栈顶元素>当前元素arr[i],则将其弹出,直到栈顶元素<=arr[i],
      栈顶元素即为右边第一个<=arr[i]的元素arr[k],此时right[i]=k-i
    • 连续子数组arr[j],arr[j+1],…,arr[k]的最小元素即为arr[i],以arr[i]为最小元素的连续子序列数量为 ( i − j ) ∗ ( k − i ) (i-j)*(k-i) (i−j)∗(k−i)
    class Solution {
        public int sumSubarrayMins(int[] arr) {
            int n=arr.length;
            int[] left=new int[n];
            int[] right=new int[n];
            Deque<Integer>stack=new ArrayDeque<>();
            //计算left
            for(int i=0;i<n;i++){
                while(!stack.isEmpty()&&arr[i]<=arr[stack.peek()])
                    stack.poll();
                if(!stack.isEmpty())
                    left[i]=i-stack.peek();
                else
                    left[i]=i+1;
                stack.push(i);
            }
            stack.clear();
            //计算right
            for(int i=n-1;i>=0;i--){
                while(!stack.isEmpty()&&arr[i]<arr[stack.peek()])
                    stack.poll();
                if(!stack.isEmpty())
                    right[i]=stack.peek()-i;
                else
                    right[i]=n-i;
                stack.push(i);
            }
            //计算结果
            long res=0;
            final int MOD=1000000007;
            for(int i=0;i<n;i++){
                res=(res+(long)left[i]*right[i]*arr[i])%MOD;
            }
            return (int)res;
        }
    }
    
    • 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
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

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

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

    单调栈+动态规划

    1. 状态定义:s[i][j] 表示子数组[ arr[j], arr[j+1],…,arr[i] ]的最小值

    2. 状态转移方程:
      假设以arr[i]为最右且最小的最长子序列长度为k:
      j>=i-k+1时,s[j][i]=arr[i]
      j 在这里插入图片描述

    3. 初始条件:
      dp[i]=0

    4. 返回值:dp[i] 的和,0<=i<=n-1

    算法

    • 从左向右遍历数组并维护一个单调递增的栈,如果栈顶元素>=当前元素arr[i],则弹出栈,此时栈顶元素即为左边第一个<当前值的元素
    • 求出以当前值为最右且最小的子序列长度 k,根据递推公式求出 dp[i],返回dp[i] 的和,0<=i<=n-1
    class Solution {
        public int sumSubarrayMins(int[] arr) {
            int n=arr.length;
            int[] dp=new int[n];
            long res=0;
            final int MOD=1000000007;
            Deque<Integer>stack=new ArrayDeque<>();
            for(int i=0;i<n;i++){
                //维护单调栈
                while(!stack.isEmpty()&&arr[i]<=arr[stack.peek()])
                    stack.poll();
                int k=stack.isEmpty()?i+1:i-stack.peek();//以arr[i]为最右且最小的最长子序列长度
                dp[i]=k*arr[i]+(stack.isEmpty()?0:dp[i-k]);
                res=(res+dp[i])%MOD;
                stack.push(i);
            }
            return (int)res;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

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

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

  • 相关阅读:
    蚱蜢优化算法(Matlab代码实现)
    Springboot----项目整合微信支付(利用RabbitMQ延迟队列处理用户退款)
    Android移动应用开发之TextView实现阴影跑马灯文字效果
    案例精选|聚铭日志审计+聚铭下一代防火墙共同防护常宁市永新能源科技有限公司内网安全
    精美可视化:Python自动化生成漂亮的测试报告
    如何用 Markdown 写出可以在各个平台兼容方便查看并且非常好看的readme或文章?附详细举例图文说明、工具、模版
    1013;温度表达转换
    PADA: Example-based Prompt Learning for on-the-fly Adaptation to Unseen Domains
    【Qt】QTextEdit/QPlainTextEdit 实现 Tab 键多行缩进与反缩进
    linux驱动开发:中断和时间管理
  • 原文地址:https://blog.csdn.net/qq_43417265/article/details/127567948
  • 最新文章
  • 沪漂五周年了:我越来越迷茫了
    Agentic Skill Routing 实战:别再把所有 Skill 塞进 AI Agent 上下文
    MySQL-Seconds_behind_master的精度误差
    [MAF预定义ChatClient中间件-03]CachingChatClient——利用缓存省钱省时间
    AI的至暗历史:从万众期待到被政府撤资,AI的两次死亡徘徊
    Agent OS :五种驯服不确定性的范式
    PortSwigger SQL注入LAB11
    数据库即时编译JIT
    [Begin]AI Learn Data Day 0
    深度学习进阶(二十七)现代 LLM 的核心架构设计其二:SwiGLU
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
小工具 小游戏
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1

京公网安备 11010502049817号