第315场周赛hard题,没有想出来,在此做记录,参考了三位大佬的题解:
思路
本题思路相当于把一个连续的数组分为若干个块,每个块外为[minK, maxk]
范围外的数字,块内为范围内的数字,且包含有minK
和maxK
。以下图为例:
minK = 2
,maxK = 4
遍历nums
,记录每个块中最后出现的maxK
以及minK
出现的位置下标lastMax
以及lastMin
。
在每一个块内部,假设其起始坐标为0
,且块内下标lastMax
以及lastMin
已经得到,则遇到下一个[minK, maxK]
范围内的数时,以这个数下标为右边界,左边界可在[0, min(lastMax, lastMin)]
中任意取得。即可得ans += min(lastMax, lastMin)
。
在遍历的时候,每个块的起始坐标不为0,可以额外维护一个变量outI
,表示最后一个范围外的数的下标。若min(lastMax, lastMin) < outI
,说明outI
右侧maxK
和minK
还没有全部出现,因此此时当前答案加0。
代码如下:
class Solution {
public:
long long countSubarrays(vector<int>& nums, int minK, int maxK) {
int lastMin = -1, lastMax = -1, outI = -1;
long long ans = 0;
for(int i=0; i< nums.size(); ++i){
//枚举右边界
if(nums[i] == minK){
lastMin = i;
}
if(nums[i] == maxK){
lastMax = i;
}
if(nums[i] < minK || nums[i] > maxK){
outI = i;
}
ans += max(min(lastMin, lastMax) - outI, 0);
}
return ans;
}
};