当前位置:网站首页>leetcode:2104. 子数组范围和
leetcode:2104. 子数组范围和
2022-06-24 21:21:00 【OceanStar的学习笔记】
题目来源
题目描述


class Solution {
public:
long long subArrayRanges(vector<int>& nums) {
}
};
题目解析
单调栈
因为需要最大元素、最小元素,所以应该想办法把问题转换为单调栈。
由于我们要求的是所有子数组最大元素和最小元素的差值。因此,我们考虑每个元素成为了多少个区间的最大值,还有多少个区间的最小值。前者的数量就是该元素在累计求和中被加的次数,后者则是被减的次数。
这样我们只需要一种遍历一遍的方式获得每个元素是多少个区间的最大最小值即可在O(n)的时间里求出结果。
考虑一个具体的例子: [ 2 , 3 , 5 , 4 , 10 , 2 ] [2, 3, 5, 4, 10, 2] [2,3,5,4,10,2]
- 我们考虑中间的某个数字4,它是多少区间的最大值呢?首先,左侧的5,就决定了,4为最大值的区间左边界不可能比5靠左;右侧的10也做出了同样的限制。所以4只能是自己这个区间的最大值。
- 那他又是多少区间的最小值呢,我们往左看,第一个小于4的值是3,所以5开始往右的位置可以做左边界;右边第一个小于4的值是2,所以10往左的位置可以做右边界。
- 假设当前值下标为i;左侧第一个小于该元素的下标为l,右侧为r。则以i为最小值的区间数量,通过组合计数原理,可以得到,为 ( i − l ) ∗ ( r − i ) (i-l)*(r-i) (i−l)∗(r−i)
而最小值怎么维护呢?我们用一个单调增栈即可,从左往右遍历,如果栈顶元素大于当前值,我们就出栈;直到栈顶元素小于当前值,这样我们就知道了小于当前值最近的左侧元素是在哪了。
右侧和最大值的计算过程类似。
还有一个小细节,就是数组中会有重复的元素;为了避免重复区间的计算,从左往右和从右往左的统计,我们需要分别用开区间和闭区间来表示。
class Solution {
public:
long long subArrayRanges(vector<int>& nums) {
int m = nums.size();
std::vector<int> lsmall(m, 0);
std::vector<int> rsmall(m, 0);
std::vector<int> llarge(m, 0);
std::vector<int> rlarge(m, 0);
std::stack<int> s; //从左往右单调增栈
// 从左往右单调增栈 不能出栈的时候栈顶就是当前元素左侧最近的小于当前元素的节点
s.push(-1);
for (int i = 0; i < m; ++i) {
while (s.top() != -1 && nums[s.top()] >= nums[i]) {
s.pop();
}
lsmall[i] = s.top();
s.push(i);
}
// 从右往左单调增栈 不能出栈的时候栈顶就是当前元素右侧最近的小于当前元素的节点
s = stack<int>();
s.push(m);
for (int i = m-1; i >= 0; i--) {
while (s.top() != m && nums[s.top()] > nums[i]) {
s.pop();
}
rsmall[i] = s.top();
s.push(i);
}
// 从左往右单调减栈 不能出栈的时候栈顶就是当前元素左侧最近的大于当前元素的节点
s = stack<int>();
s.push(-1);
for (int i = 0; i < m; i++) {
while (s.top() != -1 && nums[s.top()] <= nums[i]) {
s.pop();
}
llarge[i] = s.top();
s.push(i);
}
// 从右往左单调增栈 不能出栈的时候栈顶就是当前元素右侧最近的大于当前元素的节点
s = stack<int>();
s.push(m);
for (int i = m-1; i >= 0; i--) {
while (s.top() != m && nums[s.top()] < nums[i]) {
s.pop();
}
rlarge[i] = s.top();
s.push(i);
}
long long ans = 0;
for (int i = 0; i < m; ++i) {
ans += nums[i] * 1L * (i - llarge[i]) * (rlarge[i] - i);
ans -= nums[i] * 1L * (i - llarge[i]) * (rlarge[i] - i);
}
return ans;
}
};
边栏推荐
猜你喜欢

"One good programmer is worth five ordinary programmers!"

新一代可级联的以太网远程I/O数据采集模块

Bi-sql like

利用 Redis 的 sorted set 做每周热评的功能

Boutique enterprise class powerbi application pipeline deployment

Deep learning LSTM model for stock analysis and prediction

JVM指令

Powerbi - for you who are learning

4年工作经验,多线程间的5种通信方式都说不出来,你敢信?

2种常见的设备稼动率OEE监测方法
随机推荐
Tencent cloud wecity Industry joint collaborative innovation to celebrate the New Year!
[practical series] full WiFi coverage at home
Texture enhancement
excel 汉字转拼音「建议收藏」
[untitled]
腾讯云WeCity解决方案
Yasea APK Download Image
sql 聚合函数有哪些
JVM directive
Audio PCM data calculates sound decibel value to realize simple VAD function
Activity lifecycle
Is it reliable to open an account on the flush with a mobile phone? Is there any hidden danger in this way
ImageView shows network pictures
Program.launch(xxx)打开文件
腾讯搬家了!
Ecological escort cloud service providers wave "Intel flag"
Picture rotation move zoom gradient
IPC机制
丹麦技术大学首创将量子计算应用于能源系统潮流建模
Bi SQL drop & alter