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


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

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

    max(arr[i..j])表示子数组arr[i..j]中的最大值,min(arr[i..j])表示子数组arr[i..j]中的最小值

    要求:如果数组长度为N,请实现时间复杂度为 O(N) 的解法。

    生成两个双端队列 qmax 和 qmin。当子数组为 arr[i..j] 时,qmax 维护了窗口数组 arr[i..j] 的最大值更新的结构,qmin 维护了窗口子数组 arr[i..j] 的最小值更新的结构。当子数组 arr[i..j] 向右扩一个位置变成 arr[i..j+1] 时,qmax 和 qmin 结构在 O(1) 的时间内更新,并且可以在 O(1)的时间内得到 arr[1..j+1] 的最大值和最小值。当子数组 arr[i..j] 向右缩一个位置变成 arr[i+1..j]时,qmax 和 qmin 结构依然可以在 O(1)的时间内更新,并且在O(1)的时间内得到 arr[i+1..j] 的最大值和最小值。

    通过分析题目满足的条件,可以得到如下两个结论:

    1. 如果子数组 arr[i..j] 满足条件,即 max(arr[i..j])-min(arr[i..j])<=num,那么 arr[i..j] 中的每个子数组,即 arr[k..l](i<=k<=l<=j) 满足条件。我们以子数组 arr[i..j-1] 为例说明,arr[i..j-1] 最大值只可能小于或等于 arr[i..j] 的最大值,所以 arr[i..j-1] 必然满足条件。同理,arr[i..j] 中的每一个子数组都满足条件。

    2. 如果子数组 arr[i..j] 不满足条件,那么所有包含 arr[i..j] 的子数组,即 arr[k..l](k<=i<=j<=l) 都不满足条件。

    设计整个过程如下:

     1     public int getNum(int[] arr, int num)
     2     {
     3         if(arr == null || arr.length == 0)
     4             return 0;
     5 
     6         Deque<Integer> qmax = new LinkedList<Integer>();
     7         Deuqe<Integer> qmin = new LinkedList<Integer>();
     8         int i = 0, j = 0, res = 0;
     9         while(i < arr.length)
    10         {
    11             while(j < arr.length)
    12             {
    13                 while(!qmax.isEmpty() && arr[qmax.peekLast()] <= arr[i])
    14                 {
    15                     qmax.pollLast();
    16                 }
    17                 qmax.addLast(i);
    18             
    19                 while(!qmin.isEmpty() && arr[qmin.peekLast()] >= arr[i])
    20                 {
    21                     qmin.pollLast();
    22                 }
    23                 qmin.addLast(i);
    24 
    25                 if(qmax.peekFirst() - qmin.peekFirst() > num)
    26                 {
    27                     break;
    28                 }
    29                 j++;
    30             }
    31 
    32             if(qmin.peekFirst() == i)
    33                 qmin.pollFirst();
    34 
    35             if(qmax.peekFirst() == i)
    36                 qmax.pollFirst();
    37 
    38             res += j - i;
    39             i++;
    40         }
    41 
    42         return res;
    43     }

     参考资料:程序员代码面试指南 IT名企算法与数据结构题目最优解,左程云

  • 相关阅读:
    Flex AIR应用GPS定位功能(Android和IOS)
    Flex AIR应用拍照功能(Android和IOS版本)
    读取Flex AIR应用程序设置
    查看本机开放的端口号,查看某个端口号是否被占用,查看被占用的端口号被哪个进程所占用,如何结束该进程
    Eclipse设置默认编码为UTF-8
    Eclipse使用教程之精华篇
    hdu 1829 分组并查集
    hdu 1316高精度
    hdu 4287 字典树问题
    hdu 1867 kmp共工前后缀串问题
  • 原文地址:https://www.cnblogs.com/2015110615L/p/6659303.html
Copyright © 2020-2023  润新知