[程序员代码面试指南] 最大值减去最小值小于或等于num的子数组数量

[程序员代码面试指南] 最大值减去最小值小于或等于num的子数组数量

题目描述:

给定数组arr和整数num,返回共有多少个子数组满足如下情况:

max(arr[i..j])-min(arr[i..j])<=num

分析:

  1. 利用滑动窗口进行计算, [i..j] 用两个指针 i j 表示,其子数组.
  2. 用两个双端数组分别维护这个窗口内的最大值和最小值
  3. 从数组arr的每个位置开始扩张(max-min<=num),直至不能扩张.此时,满足条件的子数组数量为 j-i;
  4. 不满足条件呢,需要窗口左移即i++ . 然后更新一下两个双端队列

实现:

int getNum(vector<int> arr, int num) {

    if (arr.size() == 0)
        return 0;

    int res = 0;
    deque<int> qMin;
    deque<int> qMax;
    int i = 0;
    int j = 0;

    while (i < arr.size()) {
        while (j < arr.size()) {
            // 大于等于arr[j],则不可能成为最小值,所以要pop掉
            while (!qMin.empty() && arr[qMin.back()] >= arr[j]) {
                qMin.pop_back();
            }
            qMin.push_back(j);
            // 小于等于arr[j],则不可能成为最大值,所以要pop掉
            while (!qMax.empty() && arr[qMax.back()] <= arr[j]) {
                qMax.pop_back();
            }
            qMax.push_back(j);

            // 不满足条件则break,计算子数组个数
            if (arr[qMax.front()] - arr[qMin.front()] > num) {
                break;
            }
            j++;
        }
        res += j - i;
        // 更新qMin和qMax 窗口是否过期的检测
        if (qMin.front() == i) {
            qMin.pop_front();
        }
        if (qMax.front() == i) {
            qMax.pop_front();
        }
    }
    return res;
}

体会:

  • 动态维护一个窗口.可以使用双端队列 dequeue
  • 窗口是否过期的检测

参考文档

算法题-最大值减去最小值小于或等于 num 的子数组数量

猜你喜欢

转载自blog.csdn.net/qjh5606/article/details/85314711
今日推荐