LeetCode-2104 子数组范围和
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sum-of-subarray-ranges
题目描述
给你一个整数数组 nums 。nums 中,子数组的 范围 是子数组中最大元素和最小元素的差值。
返回 nums 中 所有 子数组范围的 和 。
子数组是数组中一个连续 非空 的元素序列。
示例 1:
输入:nums = [1,2,3]
输出:4
解释:nums 的 6 个子数组如下所示:
[1],范围 = 最大 - 最小 = 1 - 1 = 0
[2],范围 = 2 - 2 = 0
[3],范围 = 3 - 3 = 0
[1,2],范围 = 2 - 1 = 1
[2,3],范围 = 3 - 2 = 1
[1,2,3],范围 = 3 - 1 = 2
所有范围的和是 0 + 0 + 0 + 1 + 1 + 2 = 4
示例 2:
输入:nums = [1,3,3]
输出:4
解释:nums 的 6 个子数组如下所示:
[1],范围 = 最大 - 最小 = 1 - 1 = 0
[3],范围 = 3 - 3 = 0
[3],范围 = 3 - 3 = 0
[1,3],范围 = 3 - 1 = 2
[3,3],范围 = 3 - 3 = 0
[1,3,3],范围 = 3 - 1 = 2
所有范围的和是 0 + 0 + 0 + 2 + 0 + 2 = 4
示例 3:
输入:nums = [4,-2,-3,4,1]
输出:59
解释:nums 中所有子数组范围的和是 59
提示:
1 <= nums.length <= 1000
-109 <= nums[i] <= 109
解题思路
首先看数据范围,可以通过暴力法来做,遍历子数组,分别求出最大值最小值然后求和,时间复杂度是O(n2)
还有一种巧妙的方法可以将时间复杂度压缩到O(n)。
对于第i个数ai,如果左边第一个比他小的数下标为left,第一个比他小的数下标位right,那么(left,right)中所有的子数组最小值都是ai,在(left,right)中共有(right - i) * (i - left) 个子数组,那么(left, right)范围内子数组最小值的和为(right - i) * (i - left) * ai,同理可以求出(left, right)范围内子数组最大值的和,两个相减就可以求出(left, right)范围内的范围和。
问题转化为了如何第i个数左边小值和大值及右边的小值和大值,使用单调栈一次遍历便可以分别求得这四个值,并且用vector将下标存起来。
代码展示
暴力法:
class Solution {
public:
long long subArrayRanges(vector<int>& nums) {
int n = nums.size();
long long ret = 0;
for (int i = 0; i < n; i++) {
int minVal = INT_MAX, maxVal = INT_MIN;
for (int j = i; j < n; j++) {
minVal = min(minVal, nums[j]);
maxVal = max(maxVal, nums[j]);
ret += maxVal - minVal;
}
}
return ret;
}
};
单调栈+数学:
class Solution {
public:
long long subArrayRanges(vector<int>& nums) {
int n = nums.size();
long long ret = 0;
vector<int> viLeftMin(n), viRightMin(n), viLeftMax(n), viRightMax(n);
stack<int> siMax, siMin;
for(int i = 0; i < n; i++)
{
while(!siMin.empty() && nums[siMin.top()] > nums[i])
siMin.pop();
viLeftMin[i] = siMin.empty()? -1: siMin.top();
siMin.push(i); while(!siMax.empty() && nums[siMax.top()] <= nums[i])
siMax.pop();
viLeftMax[i] = siMax.empty()? -1: siMax.top();
siMax.push(i);
}
siMax = stack<int>();
siMin = stack<int>();
for(int i = n - 1; i >= 0; i--)
{
while(!siMin.empty() && nums[siMin.top()] >= nums[i])
siMin.pop();
viRightMin[i] = siMin.empty()? n: siMin.top();
siMin.push(i); while(!siMax.empty() && nums[siMax.top()] < nums[i])
siMax.pop();
viRightMax[i] = siMax.empty()? n: siMax.top();
siMax.push(i);
} for(int i = 0; i < n; i++)
{
ret += ((((long long)viRightMax[i] - i) * (i - viLeftMax[i])) - (((long long)viRightMin[i] - i) * (i - viLeftMin[i])))* nums[i];
}
return ret;
}
};
运行结果
LeetCode-2104 子数组范围和的更多相关文章
- LeetCode 643. 子数组最大平均数 I(Maximum Average Subarray I)
643. 子数组最大平均数 I 643. Maximum Average Subarray I 题目描述 给定 n 个整数,找出平均数最大且长度为 k 的连续子数组,并输出该最大平均数. LeetCo ...
- Leetcode 643.子数组最大平均数I
子数组最大平均数I 给定 n 个整数,找出平均数最大且长度为 k 的连续子数组,并输出该最大平均数. 示例 1: 输入: [1,12,-5,-6,50,3], k = 4 输出: 12.75 解释: ...
- Java实现 LeetCode 643 子数组最大平均数 I(滑动窗口)
643. 子数组最大平均数 I 给定 n 个整数,找出平均数最大且长度为 k 的连续子数组,并输出该最大平均数. 示例 1: 输入: [1,12,-5,-6,50,3], k = 4 输出: 12.7 ...
- [LeetCode] Minimum Size Subarray Sum 最短子数组之和
Given an array of n positive integers and a positive integer s, find the minimal length of a subarra ...
- LeetCode 560. Subarray Sum Equals K (子数组之和等于K)
Given an array of integers and an integer k, you need to find the total number of continuous subarra ...
- [LeetCode] Maximum Sum of 3 Non-Overlapping Subarrays 三个非重叠子数组的最大和
In a given array nums of positive integers, find three non-overlapping subarrays with maximum sum. E ...
- [LeetCode] Maximum Average Subarray II 子数组的最大平均值之二
Given an array consisting of n integers, find the contiguous subarray whose length is greater than o ...
- [LeetCode] Subarray Product Less Than K 子数组乘积小于K
Your are given an array of positive integers nums. Count and print the number of (contiguous) subarr ...
- [LeetCode] Maximum Average Subarray I 子数组的最大平均值
Given an array consisting of n integers, find the contiguous subarray of given length k that has the ...
- [LeetCode] Subarray Sum Equals K 子数组和为K
Given an array of integers and an integer k, you need to find the total number of continuous subarra ...
随机推荐
- Github Actions 学习笔记
Github Actions是什么? Github Actions 官方介绍:GitHub Actions是一个持续集成和持续交付(CI/CD)平台,允许您自动化构建.测试和部署管道.您可以创建构建和 ...
- Jmeter 之提取的值为null时,if控制器中的判断表达式
场景:当level的值为null时则执行 {"code":0, "msg":null, "data": [ { "level&qu ...
- VSCTF的Recovery
题目如下: from random import randint from base64 import b64encode def validate(password: str) -> bool ...
- [常用工具] C++环境下Qt的安装
文章目录 1 Qt(C++)版本的选择 2 Qt 安装 2.1 Qt 6.3.1的安装 2.2 Qt 5.14.2的安装 3 Qt 其他版本安装 1 Qt(C++)版本的选择 Qt(C++)是一个跨平 ...
- 深入Typescript--02-Typescript数据类型
基本类型 一.最最基础的类型 布尔.数字.字符串类型 let bool:boolean = true; let num:number = 10; let str:string = 'hello wor ...
- 高并发环境下3种方式优化Tomcat性能
摘要:Tomcat作为最常用的Java Web服务器,随着并发量越来越高,Tomcat的性能会急剧下降,那有没有什么方法来优化Tomcat在高并发环境下的性能呢? 本文分享自华为云社区<[高并发 ...
- file过滤器的原理和使用-FileNameFilter过滤器的使用和lambda优化程序
file过滤器的原理和使用 java.io.FileFilter是一个接口,是File的过滤器.该接口的对象可以传递给File类的listFiles(FileFilter)作为参数,接口中只有一个方法 ...
- Java 进阶P-2.5+P-2.6
包 Java 包(package) 为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间. 包的作用 1.把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用. 2.如同文件夹一 ...
- 学习ASP.NET Core Blazor编程系列二十三——登录(3)
学习ASP.NET Core Blazor编程系列文章之目录 学习ASP.NET Core Blazor编程系列一--综述 学习ASP.NET Core Blazor编程系列二--第一个Blazor应 ...
- 11月9日内容总结——单例模式的多种实现方式、pickle序列号模块和选课系统
目录 一.单例模式实现的多种方式 方式一:使用类 方法二:使用metaclass方式(自定义元类) 方法三:自定义双下new 方法四:基于模块的单例模式 二.pickle序列化模块 优势: 缺陷: 方 ...