最大值减最小值满足条件的子数组

介绍

求出一个数组中最大值减去最小值小于等于某个数的子数组的个数O(N)时间复杂度

思想

使用两个双端队列结构,一个用于维护当前子数组中的最大值,一个用于维护当前子数组中的最小值
双端队列的维护详见双端队列
首先我们需要知道一下结论:
如果一个子数组左端标记为L,右端标记为R,那么:
(1)如果从L到R构成的子数组可以满足条件,则该子数组中的任意一个子数组都满足条件;
(2)如果从L到R构成的子数组不满足条件,则包含改数组的任何一个数组都不满足条件。
我们一次遍历数组的每一个位置,当前位置记为L,R记为由当前位置可以构成的满足条件的最长子数组,则当由当前位置形成的满足条件的子数组个数为R-L;当无法以L形成满足条件的子数组时L++,并维护一下最大值和最小值的双端队列。

完整代码

#include <iostream>
#include <deque>
using namespace std;

//最大值减去最小值小于或等于num的子数组


int getNum(int arr[], int size, int num){
    deque<int> minQ;
    deque<int> maxQ;
    int L = 0;
    int R = 0;
    int res = 0;
    while(L < size){
        while(R < size){
            while(!minQ.empty() && arr[minQ.back()] >= arr[R]){
                minQ.pop_back();
            }
            minQ.push_back(R);
            while(!maxQ.empty() && arr[maxQ.back()] <= arr[R]){
                maxQ.pop_back();
            }
            maxQ.push_back(R);
            if(arr[maxQ.front()]-arr[minQ.front()] > num){
                    break;

            }
            R++;
        }
        res += R-L;
        if(maxQ.front() == L){
            maxQ.pop_front();
        }
        if(minQ.front() == L){
            minQ.pop_front();
        }
        L++;
    }
    return res;
}

int main()
{
    int n, num;
    cin >>n >> num;
    int *arr = new int[n];
    for(int i = 0; i < n; i++) cin >> arr[i];
    cout << getNum(arr, n, num) << endl;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值