zoukankan      html  css  js  c++  java
  • 数据结构--最大值减去最小值小于或等于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.中的最小值。
    【要求】
    如果数组长度为N, 请实现时间复杂度为O(N)的解法。

    子数组要求其中的元素是连续

    解法一:暴力法  O(N³)  不可取

    通过循环,找遍数组中所有的子数组,同时判断子数组中的值是否满足条件,如果满足,则加入到结果中

    解法二:

    ①、如果一个子数组从L->R中,arr[max] - arr[min] <= num,那么在L->R范围内的子数组都符合要求

    ②、如果一个子数组从L->R中,arr[max] - arr[min] > num,那么以L->R为基础向外扩的子数组都不符合要求

    做两个双端队列,一个是窗口内最大值,另外一个是窗口内最小值

    1)、开始时L在数组最左端 0 位置,R从最左端开始向右扩,直到再扩充一个值就不符合要求时,R停止,设此时为 x 位置

    则以0位置开始的子数组有 x + 1个(0,0~1,……0~x)  这些子数组是以0为起始位置符合要求的所有子数组个数

    2)、L向右边移动一个位置,更新两个窗口内的结构,然后R试着继续向右扩,重复上面的,然后就能得到以1为起始位置符合要求的所有子数组个数

    L每次向右移动一个位置,R就开始向右扩

    /**
     * Created by Skye on 2018/5/3.
     * 给定数组arr和整数num, 共返回有多少个子数组满足如下情况:
     max(arr[i..j]) - min(arr[i..j]) <= num
     max(arr[i..j])表示子数组arr[i..j]中的最大值, min(arr[i..j])表示子数组arr[i.中的最小值。
     【要求】
     如果数组长度为N, 请实现时间复杂度为O(N)的解法。
    
    
     从当前位置 i 开始 采用双重循环, j 向后面开始扩充,采用两个队列,分别记录当前 i - j 的最大值和最小值
     当 arrays[maxList.peekLast()] - arrays[minList.peekLast()] > num 时不满足题意,
     则 j 停止扩充,然后计算从 i 到 j 共有多少个子数组  j - i 记录,
     并且判断当前位置 i 是否还在最大或最小队列中,如果存在,则弹出,因为 i 马上要过期了
     然后 i++ 继续扩充
     */
    public class AllLessNumSubArray {
    
        public static int lessNumArray(int[] arrays, int num){
            if(arrays == null || arrays.length == 0) return 0;
            LinkedList<Integer> maxList = new LinkedList<>();
            LinkedList<Integer> minList = new LinkedList<>();
            int res = 0;
            int i = 0;
            int j = 0;
            while(i < arrays.length){
                while(j < arrays.length){
                    while(!maxList.isEmpty() && arrays[maxList.peekLast()] <= arrays[j]){
                        maxList.pollLast();
                    }
                    while(!minList.isEmpty() && arrays[minList.peekLast()] >= arrays[j]){
                        minList.pollLast();
                    }
                    maxList.addLast(arrays[j]);
                    minList.addLast(arrays[j]);
                    j++;
                    if(arrays[maxList.peekLast()] - arrays[minList.peekLast()] > num){
                        break;
                    }
                }
                //判断是否超过了边值条件
                if(maxList.peekFirst() == i) maxList.pollFirst();
                if(minList.peekFirst() == i) minList.pollFirst();
                res += j - i;
                i++;
            }
            return res;
        }
    }
    

      

  • 相关阅读:
    Dockerfile基于centos镜像编译安装httpd
    Dockerfile基于centos镜像编译安装nginx
    Dockerfile介绍和常用指令
    Docker存储卷
    正则表达式
    Sed与Awk
    Shell函数
    Shell脚本基础
    Autofs
    Podman
  • 原文地址:https://www.cnblogs.com/SkyeAngel/p/8985801.html
Copyright © 2011-2022 走看看