Decrisption

Given an array of integers arr, find the sum of min(b), where b ranges over every (contiguous) subarray of arr. Since the answer may be large, return the answer modulo \(10^9\) + 7.

Input

Example 1:

Input: \(arr = [3,1,2,4]\)

Output: 17

Explanation:

Subarrays are [3], [1], [2], [4], [3,1], [1,2], [2,4], [3,1,2], [1,2,4], [3,1,2,4].

Minimums are 3, 1, 2, 4, 1, 1, 2, 1, 1, 1.

Sum is 17.

Example 2:

Input: \(arr = [11,81,94,43,3]\)

Output: 444

Constraints

\(1\leq arr.length\leq3*10^4\)

\(1\leq arr[i]\leq3*10^4\)

Solution

思路:

方法一:暴力计算

直接计算每一个子数组中的最小值并全部相加,时间复杂度为\(O\)(\(n^2\)),显然会超时。

class Solution {
public:
int MOD=1e9+7;
int sumSubarrayMins(vector<int>& arr) {
int n=arr.size();
int ans=0;
for(int i=0;i<n;i++){
for(int j=0;j<=i;j++){
int min=*min_element(arr.begin()+j,arr.begin()+i+1);
ans+=min;
ans%=MOD;
}
}
return ans;
}
};

方法二:两次单调栈+贡献法

方法一中由于重复计算了许多次相同的最小值,所以我们要想办法免去复杂计算。对于数组中的每一个元素,其都会在最终的答案中有一个贡献值。该贡献值可以看成是每一个元素作为子数组的最小元素的次数。

注意到:对于某一个元素\(x\),假定其下标为\(i\),如果x是某一个子数组的最小值,该子数组的左端点为\(left\),右端点为\(right\),那么在[\(left\),\(right\)]范围内所有包含\(x\)的子数组的最小值都为x,x的贡献为\(arr[i]\)\(*\)(\(i-left\))\(*\)(\(right-i\))。所以我们要找到每一个元素左侧第一个小于该元素的位置\(left\)和右侧第一个小于该元素的位置\(right\)。这样在区间\((left,right)\)范围内包含\(x\)的子数组的最小值可以确定为x,x的贡献值为\(arr[i]*(i-left)*(right-i)\).

class Solution {
public:
int MOD=1e9+7;
typedef long long ll;
int sumSubarrayMins(vector<int>& arr) {
int n=arr.size();
ll ans=0;
vector<ll> left(n,-1); //左边界为-1
vector<ll> right(n,n); //右边界为n
stack<ll> stk;
for(int i=0;i<n;i++){
while(!stk.empty()&&arr[stk.top()]>arr[i]){
stk.pop();
}
if(!stk.empty()){
left[i]=stk.top();
}
stk.push(i);
} while(!stk.empty()) stk.pop(); for(int i=n-1;i>=0;i--){
while(!stk.empty()&&arr[stk.top()]>=arr[i]){
stk.pop();
}
if(!stk.empty()){
right[i]=stk.top();
}
stk.push(i);
} for(ll i=0;i<n;i++){
ans+= (ll)arr[i]*(i-left[i])*(right[i]-i);
ans%=MOD;
}
return ans;
}
};

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

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

【LeetCode】 907 子数组的最小值之和的更多相关文章

  1. [Swift]LeetCode907. 子数组的最小值之和 | Sum of Subarray Minimums

    Given an array of integers A, find the sum of min(B), where B ranges over every (contiguous) subarra ...

  2. Leetcode 643.子数组最大平均数I

    子数组最大平均数I 给定 n 个整数,找出平均数最大且长度为 k 的连续子数组,并输出该最大平均数. 示例 1: 输入: [1,12,-5,-6,50,3], k = 4 输出: 12.75 解释: ...

  3. LeetCode 643. 子数组最大平均数 I(Maximum Average Subarray I)

    643. 子数组最大平均数 I 643. Maximum Average Subarray I 题目描述 给定 n 个整数,找出平均数最大且长度为 k 的连续子数组,并输出该最大平均数. LeetCo ...

  4. Java实现 LeetCode 643 子数组最大平均数 I(滑动窗口)

    643. 子数组最大平均数 I 给定 n 个整数,找出平均数最大且长度为 k 的连续子数组,并输出该最大平均数. 示例 1: 输入: [1,12,-5,-6,50,3], k = 4 输出: 12.7 ...

  5. [LeetCode] 907. Sum of Subarray Minimums 子数组最小值之和

    Given an array of integers A, find the sum of min(B), where B ranges over every (contiguous) subarra ...

  6. [LeetCode] Continuous Subarray Sum 连续的子数组之和

    Given a list of non-negative numbers and a target integer k, write a function to check if the array ...

  7. N元数组的子数组之和的最大值

    题目:有N个整数的元素的一维数组,求子数组中元素之和中最大的一组(思想:动态规划) 分析: 设该数组为array[N], 那么对于array[i]该不该在元素之和最大的那个子数组中呢?首先,不如假设a ...

  8. 152.Maximum Product Subarray---dp---连续子数组的最大乘积---《编程之美》2.13子数组的最大乘积

    题目链接:https://leetcode.com/problems/maximum-product-subarray/description/ 题目大意:给出一串数组,找出连续子数组中乘积最大的子数 ...

  9. 累加和为 K 的子数组问题

    累加和为 K 的子数组问题 作者:Grey 原文地址: 博客园:累加和为 K 的子数组问题 CSDN:累加和为 K 的子数组问题 题目说明 数组全为正数,且每个数各不相同,求累加和为K的子数组组合有哪 ...

  10. [LeetCode] Minimum Size Subarray Sum 最短子数组之和

    Given an array of n positive integers and a positive integer s, find the minimal length of a subarra ...

随机推荐

  1. Android学习——控件ProgressBar

    1.常用属性

  2. AXI 协议翻译介绍

    一.介绍 Introduction 本章描述了axis协议的体系结构和协议定义的基本事务.它包含以下部分:•第1-2页关于AXI协议•第1-3页是架构•第1-7页是基本事务•第1-11页的附加功能. ...

  3. python性能测试工具locust

    1.概述: 1.我们对目前比较流行的几款压测工具进行了调研.Jmeter与LoadRunner基于多线程实现并发,多线程由操作系统决定,由于上下文切换频繁.内核调度频繁,单台机器很难产生大量线程并发. ...

  4. Hadoop 设置静态IP、关闭防火墙

    设置静态IP [root@localhost ~]# cd /etc[root@localhost etc]# cd sysconfig[root@localhost sysconfig]# cd n ...

  5. openwrt 配置虚拟wan口

    一.刷固件:1.刷入 刷不死,百度上找教程:2.下载固件:https://downloads.openwrt.org/releases/17.01.6/targets/ramips/mt7620/ 按 ...

  6. homebrew 安装node 切换node版本

    注意:如果之前使用brew install node安装过node,需要先执行brew unlink node来'解绑'node 1.查找可用的node版本 brew search node 2.安装 ...

  7. android本地文件处理的一些经验

    选择文件后,现在一般返回 Uri contentResolver.getType(selUrl)结果如下 .txt text/plain .jpeg image/jpeg .mp4 video/mp4 ...

  8. 说说Selenium的几个痛处

    Selenium挺好用,但也有几个不爽的地方: 1. 元素无法点击,因为scroll to element这一招时常不管用 2. 调试慢,一进入调试模式,PyCharm突然变慢, evaluate如同 ...

  9. Retrofit简要分析

    Retrofit是对网络请求实现了一套请求架构封装,屏蔽底层网络实现,使网络请求像调用本地接口一样 基本使用例子 public interface GitHubService {//定义request ...

  10. 38.Ribbon

    Ribbon默认是懒加载,所以初次请求时间最长,后续请求会变快,可以通过修改为饥饿加载 ribbon.eager-load.enabled=true ribbon.eager-load.clients ...