【二叉树】【单调双向队列】LeetCode239:滑动窗口最大值
给你一个整数数组 nums 和两个整数 minK 以及 maxK 。
nums 的定界子数组是满足下述条件的一个子数组:
子数组中的 最小值 等于 minK 。
子数组中的 最大值 等于 maxK 。
返回定界子数组的数目。
子数组是数组中的一个连续部分。
示例 1:
输入:nums = [1,3,5,2,7,5], minK = 1, maxK = 5
输出:2
解释:定界子数组是 [1,3,5] 和 [1,3,5,2] 。
示例 2:
输入:nums = [1,1,1,1], minK = 1, maxK = 1
输出:10
解释:nums 的每个子数组都是一个定界子数组。共有 10 个子数组。
参数范围:
2 <= nums.length <= 105
1 <= nums[i], minK, maxK <= 106
时间复杂度: O(n) 枚举每个子数组的终点,求左边界的范围。假定i是右边界。
iMinMin | 是从nums[0,i]中从右向左第一个小于minK的下标 |
iMaxMax | 是从nums[0,i]中从右向左第一个大于maxK的下标 |
iEndMin | 是从nums[0,i]中从右向左第一个等于minK的下标 |
iEndMax | 是从nums[0,i]中从右向左第一个等于maxK的下标 |
显然left > max(iMinMin ,iMaxMax) 否则最小值更小或最大值更大
left <= min(iEndMin,iEndMax) 否则不存在minK或maxK。
class Solution {
public:
long long countSubarrays(vector<int>& nums, int minK, int maxK) {
int iMinMin = -1, iMaxMax = -1;
int iEndMin = -1, iEndMax = -1;
long long llRet = 0;
for (int i = 0; i < nums.size(); i++)
{
const auto& n = nums[i];
if (n > maxK)
{
iMaxMax = i;
}
if (n < minK)
{
iMinMin = i;
}
if (n == maxK)
{
iEndMax = i;
}
if (n == minK)
{
iEndMin = i;
}
const int cur = min(iEndMin, iEndMax) - max(iMinMin, iMaxMax);
if (cur > 0)
{
llRet += cur;
}
}
return llRet;
}
};
template<class T>
void Assert(const T& t1, const T& t2)
{
assert(t1 == t2);
}
template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{
if (v1.size() != v2.size())
{
assert(false);
return;
}
for (int i = 0; i < v1.size(); i++)
{
Assert(v1[i], v2[i]);
}
}
int main()
{
vector<int> nums;
int minK, maxK;
{
Solution sln;
nums = { 1, 3, 5, 2, 7, 5 }, minK = 1, maxK = 5;
auto res = sln.countSubarrays(nums, minK, maxK);
Assert(2LL, res);
}
{
Solution sln;
nums = { 1, 1, 1, 1 }, minK = 1, maxK = 1;
auto res = sln.countSubarrays(nums, minK, maxK);
Assert(10LL, res);
}
}
class Solution {
public:
long long countSubarrays(const vector<int>& nums, const int minK, const int maxK) {
int iInvalidIndex = -1;
int iMinIndex = -1;
int iMaxIndex = -1;
long long llRet = 0;
for (int i = 0; i < nums.size(); i++)
{
if (minK == nums[i])
{
iMinIndex = i;
}
if (maxK == nums[i])
{
iMaxIndex = i;
}
if ((nums[i] > maxK) || (nums[i] < minK))
{
iInvalidIndex = i;
}
int iCur = min(iMinIndex, iMaxIndex) - iInvalidIndex;
if (iCur > 0)
{
llRet += iCur;
}
}
return llRet;
}
};
有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快
速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176
想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653
我想对大家说的话 |
---|
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。 |
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。 |
如果程序是一条龙,那算法就是他的是睛 |
操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用C++ 实现。