[程序员代码面试指南]栈和队列-最大值减去最小值 小于或等于num 的子数组的数量(双端队列)

Posted coding-gaga

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[程序员代码面试指南]栈和队列-最大值减去最小值 小于或等于num 的子数组的数量(双端队列)相关的知识,希望对你有一定的参考价值。

题目

给定数组arr和整数num,求数组的子数组中有多少个的满足“最大值减去最小值<=num”。

解题思路

  • 分析题目,有结论:
    • 如果数组arr[i...j]满足条件,则它的每一个子数组都满足条件。
    • 如果数组arr[i...j]不满足条件,则包含它的每一个数组都不满足条件。
  • 数据结构:用i、j表示当前窗口,分别使用两个双端队列维护窗口的最大值和最小值
  • 具体地,每次更新两个双端队列,检查当前的窗口是否满足条件,满足则j++,不满足则cnt+=j-i,更新双端队列,i++,j不变。若j到了len,则当前趟和剩余未遍历的都满足条件,加到cnt中。
  • 时间复杂度:i,j只需遍历一趟,时间复杂度O(n)。

    代码

import java.util.LinkedList;

public class Main {
    public static void main(String args[]) {
        int[] arr = { 1, 3, 2, 4, 5 };
        int num = 1;
        int cnt = subArrayNum(arr, num);
        System.out.println(cnt);
    }

    public static int subArrayNum(int[] arr, int num) {
        int cnt = 0;
        LinkedList<Integer> maxQue = new LinkedList<>();
        LinkedList<Integer> minQue = new LinkedList<>();
        int i = 0;
        int j = 0;
        while (i < arr.length) {
            while (j < arr.length) {
                while (!maxQue.isEmpty() && arr[maxQue.peekLast()] <= arr[j]) {
                    maxQue.pollLast();
                }
                maxQue.addLast(j);

                while (!minQue.isEmpty() && arr[minQue.peekLast()] >= arr[j]) {
                    minQue.pollLast();
                }
                minQue.add(j);

                if (arr[maxQue.peekFirst()] - arr[minQue.peekFirst()] > num) {
                    cnt += j - i;
                    if (maxQue.peekFirst() == i) {
                        maxQue.pollFirst();
                    }
                    if (minQue.peekFirst() == i) {
                        minQue.pollFirst();
                    }
                    break;// 如果break ,j不++,因为当前arr[i...j]不满足条件,不能保证arr[i+1...j]满足条件
                }

                ++j;

                if (j == arr.length) {// 说明此趟以及后面未遍历的趟的子数组全部满足条件。
                    for (; i < arr.length; ++i) {
                        cnt += j - i;
                    }
                    break;
                }
            }
            ++i;
        }
        return cnt;
    }
}

以上是关于[程序员代码面试指南]栈和队列-最大值减去最小值 小于或等于num 的子数组的数量(双端队列)的主要内容,如果未能解决你的问题,请参考以下文章

栈和队列----最大值减去最小值小于等于num的子数组的数量

左神算法书籍《程序员代码面试指南》——1_10最大值减去最小值小于或等于num的子数组数量

[程序员代码面试指南]栈和队列-生成窗口最大值数组(双端队列)

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

《程序员面试指南》第一章 栈和队列 构造数组的MaxTree

《程序员面试指南》电子书下载