【每日一题】子数组的最小值之和

文章目录

  • Tag
  • 题目来源
  • 题目解读
  • 解题思路
    • 方法一:贡献法+单调栈
  • 写在最后

Tag

【贡献法】【单调栈】【数组】【2023-11-27】


题目来源

907. 子数组的最小值之和


题目解读

计算整数数组的连续子数组中最小值的和。


解题思路

本题朴素的解决思想是求出所有的连续子数组,遍历每一个子数组然后将每一个子数组的最小和加和得到结果,但是该方法时间复杂度过高。现在介绍一种时间复杂度较优的方法——贡献法。

方法一:贡献法+单调栈

我们从数组中的每一个元素作为连续子数组中的最小值这一角度考虑,比如在数组 arr = [3, 1, 2, 4] 中,考虑 1 作为子数组中的最小值的情况,有这些子数组满足 1 是子数组中的最小值 :
[ 3 , 1 ] , [ 3 , 1 , 2 ] , [ 3 , 1 , 2 , 4 ] , [ 1 ] , [ 1 , 2 ] , [ 1 , 2 , 4 ] [3, 1], [3, 1, 2], [3, 1, 2, 4], [1], [1, 2], [1, 2, 4] [3,1],[3,1,2],[3,1,2,4],[1],[1,2],[1,2,4]
共计6个。利用乘法原理有:
6 = ( i − a ) ∗ ( b − i ) = 2 ∗ 3 6 = (i - a) * (b - i) = 2 * 3 6=(ia)(bi)=23
其中,a 表示在 arr 数组中 1 左侧比 1 小的第一个元素的下标,默认值为 -1,此时 a = -1
b 表示在 arr 数组中 1 右侧比 1 小的第一个元素的下标,默认值为 n,此时 b = n

以上是 arr 数组中无重复元素的情况,我们只需要找出元素 arr[i] 左侧第一个比它小的元素下标 a、元素 arr[i] 右侧第一个比它小的元素下标 b,利用乘法原理即可得到 arr[i] 作为连续子数组的最小值时的答案,我们遍历数组中的所有元素,计算作为连续子数组的最小值时的答案,将所有答案进行加和得到最终的答案,时间复杂度为 O ( n ) O(n) O(n)

一般的情况,若是 arr 数组中有重复元素出现会怎么样呢?此处参考 贡献法+单调栈+三种实现版本(附题单)Python/Java/C++/Go。

如果 arr 有重复元素,例如 arr=[1, 2, 4, 2, 3, 1],其中第一个 2 和第二个 2 对应的边界都是开区间 (0,5),子数组 [2, 4, 2, 3] 都包含这两个 2,这样在计算答案时就会重复统计同一个子数组,算出错误的结果。

为避免重复统计,可以修改边界的定义,把右边界改为「找小于或等于 arr[i] 的数的下标」,那么:

  • 第一个 2 对应的边界是 (0,3),子数组需要在 (0,3) 范围内且包含下标 1
  • 第二个 2 对应的边界是 (0,5),子数组需要在 (0,5) 范围内且包含下标 3
    这样以第一个 2 为最小值的子数组,就不会「越界」包含第二个 2 了,从而解决了重复统计子数组的问题。

实现代码

#define MOD 1000000007
class Solution {
public:
    int sumSubarrayMins(vector<int>& arr) {
        int n = arr.size();
        vector<int> lLessIdx(n, -1);
        vector<int> rLessAndEquIdx(n, n);

        // 用单调栈更新 lLessIdx
        int i;
        stack<int> stk;
        // [3, 1, 2, 4]
        for(i = 0; i < n; ++i) {
            while(!stk.empty() && arr[stk.top()] >= arr[i]) {
                stk.pop();
            }
            if (!stk.empty()) lLessIdx[i] = stk.top();
            stk.push(i);
        }   

        // 用单调栈更新 rLessAndEquIdx
        while (!stk.empty()) stk.pop();
        for(i = n-1; i >= 0; --i) {
            while(!stk.empty() && arr[stk.top()] > arr[i]) {
                stk.pop();
            }
            if (!stk.empty()) rLessAndEquIdx[i] = stk.top();
            stk.push(i);
        }

        long ans = 0;
        for(i = 0; i < n; ++i) {
            int a = lLessIdx[i], b = rLessAndEquIdx[i];
            ans += (long)((i - a) * (b - i)) % MOD * arr[i] % MOD; // 乘法原理
            ans %= MOD;
        }
        return (int)ans;
    }
};

复杂度分析

时间复杂度: O ( n ) O(n) O(n) n n n 是数组 arr 的长度。

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


写在最后

如果文章内容有任何错误或者您对文章有任何疑问,欢迎私信博主或者在评论区指出 💬💬💬。

如果大家有更优的时间、空间复杂度方法,欢迎评论区交流。

最后,感谢您的阅读,如果感到有所收获的话可以给博主点一个 👍 哦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/194326.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

微软重磅更新:Bing Chat全线改名Copilot,用户可免费使用GPT4!(文末附Copilot使用教程)

原创 | 文 BFT机器人 微软在2023年的Ignite大会上宣布了许多新产品和功能。其中最引人注目的是Bing Chat更名为Copilot&#xff0c;Copilot基于最新的OpenAI模型&#xff0c;包括GPT-4和DALL・E 3&#xff0c;为用户提供文本和图像生成功能。也就是说&#xff0c;只要你拥有微…

TDA4开发环境Docker化

文章目录 背景1. TDA4X Linux SDK编译环境镜像构建1.1 安装SDK1.2 验证制卡1.2.1 出现的问题:1.3 验证编译1.3.1 出现的问题2. TDA4X Linux-RT SDK编译环境镜像构建2.1 安装SDK2.2 出现的问题参考背景 开始阅读本篇前,假设你已经对docker有了一定了解,且有过docker换件搭建…

在龙蜥 anolis os 23 上 源码安装 PostgreSQL 16.1

在龙蜥 OS 23上&#xff0c;本来想使用二进制安装&#xff0c;结果发现没有针对龙蜥的列表&#xff1a; 于是想到了源码安装&#xff0c;下面我们列出了PG源码安装的步骤&#xff1a; 1.安装准备 1.1.创建操作系统组及用户 groupadd postgres useradd -g postgres -m postgr…

Windows全系列 本地密码暴力破解

首先 咱们要准备两个工具&#xff1a; 第一个是 pwdump-master 第二个是 saminside_softradar-com.exe这两个工具 我会一并上传 需要的同学 可以自取本文章操作思路是&#xff1a; 第一步 首先把我刚刚提到的两个软件 以某种手段放置于机器中 如果是真实机 就用U盘 拷贝到真实机…

sCrypt 现已支持各类主流前端框架

sCrypt 现已支持各类主流前端框架&#xff0c;包括&#xff1a; ReactNext.jsAngularSvelteVue 3.x or 2.x bundled with Vite or Webpack 通过在这些支持的前端框架中集成sCrypt开发环境&#xff0c;你可以直接在前端项目里访问合约实例和调用合约&#xff0c;方便用户使用Se…

c++容器详解Vector、deque、list、set、multiset、map、multimap、queue、stcak、Array

容器 数据结构描述实现头文件向量(vector)连续存储的元素<vector>列表(list)由节点组成的双向链表,每个结点包含着一个元素<list>双向队列(deque)连续存储的指向不同元素的指针所组成的数组<deque>集合(set)由节点组成的红黑树,每个节点都包含着一个元素,…

Java自定义一个线程池

线程池图解 线程池与主线程之间通过一个阻塞队列来平衡任务分配&#xff0c;阻塞队列中既可以满足线程等待&#xff0c;又要接收主线程的任务。 线程池实现 使用一个双向链表实现任务队列 创建任务队列 //阻塞队列 public class BlockingQueue<T> {//双线链表private …

Mysql数据库多表数据查询问题

1、背景 线上某个业务数据分表存储在10个子表中&#xff0c;现在需要快速按照条件&#xff08;比如时间范围&#xff09;筛选出所有的数据&#xff0c;主要是想做一个可视化的数据查询工具&#xff0c;给产研团队使用。 2、实践 注意&#xff1a;不要在线上真实数据库操作&am…

使用Docker compose方式安装Spug,并结合内网穿透实现远程访问

文章目录 前言1. Docker安装Spug2 . 本地访问测试3. Linux 安装cpolar4. 配置Spug公网访问地址5. 公网远程访问Spug管理界面6. 固定Spug公网地址 前言 Spug 面向中小型企业设计的轻量级无 Agent 的自动化运维平台&#xff0c;整合了主机管理、主机批量执行、主机在线终端、文件…

【Docker】python flask 项目如何打包成 Docker images镜像 上传至阿里云ACR私有(共有)镜像仓库 集成Drone CI

一、Python环境编译 1、处理好venv环境 要生成正常的 requirements.txt 文件&#xff0c;我们就需要先将虚拟环境处理好 创建虚拟环境&#xff08;可选&#xff09;&#xff1a; 在项目目录中&#xff0c;你可以选择使用虚拟环境&#xff0c;这样你的项目依赖将被隔离在一个…

3D点云目标检测:VoxelNex解读(带源码/未完)

VoxelNext 通用vsVoxelNext一、3D稀疏卷积模块1.1、额外的两次下采样1.2、稀疏体素删减 二、高度压缩三、稀疏池化四、head五、waymo数据集训练六、训练自己的数据集bug修改 通用vsVoxelNext 一、3D稀疏卷积模块 1.1、额外的两次下采样 使用通用的3D sparse conv&#xff0c;…

多线激光三维重建

交流联系点击&#xff1a;联系方式

人工智能学习2(python数据清洗)

编译工具&#xff1a;PyCharm 一.数据清洗 转化数据类型、处理重复数据、处理缺失数据 import pandas as pddf pd.read_csv("/data.csv") df.sample(10) # 用于随机获取数据并返回结果 df.head(10) # 查看前十条数据 df.tail(10) # 查看后十条数据 df.shape …

RK3568 android11 实现双路I2C触摸 --gt9xx

一&#xff0c;GT911 触摸屏简介 它的接口类型为 I2C &#xff0c;供电电压和通讯电压均为 3.3V 。这款电容触摸屏内置了上拉电阻&#xff0c;这意味着我们的开发板上与该触摸屏的接口处不需要设置上拉电阻。关于线序&#xff0c;同样是 GT911 &#xff0c;不同批次的器件都有…

从0开始学习JavaScript--JavaScript对象继承深度解析

JavaScript中的对象继承是构建灵活、可维护代码的关键部分。本文将深入讨论JavaScript中不同的继承方式&#xff0c;包括原型链继承、构造函数继承、组合继承等&#xff0c;并通过丰富的示例代码展示它们的应用和差异。通过详细解释&#xff0c;大家可以更全面地了解如何在Java…

vulfocus apache-cve_2021_41773 漏洞复现

vulfocus apache-cve_2021_41773 漏洞复现 名称: vulfocus/apache-cve_2021_41773 描述: Apache HTTP Server 2.4.49、2.4.50版本对路径规范化所做的更改中存在一个路径穿越漏洞&#xff0c;攻击者可利用该漏洞读取到Web目录外的其他文件&#xff0c;如系统配置文件、网站源码…

IDEA中也能用postman了?

Postman是大家最常用的API调试工具&#xff0c;那么有没有一种方法可以不用手动写入接口到Postman&#xff0c;即可进行接口调试操作&#xff1f;今天给大家推荐一款IDEA插件&#xff1a;Apipost Helper&#xff0c;写完代码就可以调试接口并一键生成接口文档&#xff01;而且还…

修改mysql的密码(每一步都图文解释哦)

当你想要连接本机数据库时&#xff0c;是不是有可能突然忘记了自己的数据库密码? 在此文中&#xff0c;我们来详细解决一下如何去修改自己的数据库密码&#xff0c;并使用Navicat来连接测试 1.停止mysql服务 打开终端&#xff0c;键入命令,将mysql服务先停止掉&#xff0c;…

Matlab论文插图绘制模板第128期—函数三维折线图(fplot3)

在之前的文章中&#xff0c;分享了Matlab函数折线图的绘制模板&#xff1a; 进一步&#xff0c;再来分享一下函数三维折线图。 先来看一下成品效果&#xff1a; 特别提示&#xff1a;本期内容『数据代码』已上传资源群中&#xff0c;加群的朋友请自行下载。有需要的朋友可以关…

Linux系统编程:文件系统总结

目录和文件 获取文件属性 获取文件属性有如下的系统调用&#xff0c;下面逐个来分析。 stat:通过文件路径获取属性&#xff0c;面对符号链接文件时获取的是所指向的目标文件的属性 从上图中可以看到stat函数接收一个文件的路径字符串&#xff08;你要获取哪个文件的属性&a…