给定数组 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 和 num,其中 n 表示数组 arr 的长度
第二行输入n个整数,表示数组arr中的每个元素
输出给定数组中满足条件的子数组个数
5 2 1 2 3 4 5
12
自己实现的时候注意使用下标比较还是使用值在比较,不要搞混。
import java.util.*; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int num = sc.nextInt(); int[] arr = new int[n]; for(int i = 0; i < n; i++) { arr[i] = sc.nextInt(); } int res = getArrayNum(arr, num); System.out.println(res); } //两个结论:1.到j不满足条件,a[i..j-1]满足条件所以a[m..n]都满足条件(i<=m<=n<=j-1) //2.a[i..j]不满足条件,则包含它的也都不满足条件(a[l..k],l<=i<=j<=k) //用a[i..j-1]代入条件:max(a[i..j])-min(a[i..j])<=num里进行归纳 public static int getArrayNum(int[] arr, int num) { //判空 if(arr == null || arr.length == 0){ return 0; } //拿LinkedList作为双端队列来使用 LinkedList qmax = new LinkedList(); LinkedList qmin = new LinkedList(); //j是不重置的,因为上面两个结论,到j不满足条件时,j是不变的,所以j只会不断地增长 //j不重置则使用while语句 int i = 0; int j = 0; int result = 0; //到j不满足条件时,i..j-1所有的子数组都满足条件,但是计数的时候只计算了从i开头的 //后面剩下的会到它们为开头的时候计算(如i+1),这也是j不重置的原因 while(i < arr.length){ while(j < arr.length){ //为了保证同一个下标只进栈一次,出栈一次,这样时间复杂度才能保证(每个元素O(1),n个元素O(n)) //如果break,j不变,而qmin.peekLast()正好是上一轮的j,后面i++,所以判断[i+1..j]是否满足条件 //到j不满足条件,所以[i+1..j]不一定满足条件 if(qmin.isEmpty() || qmin.peekLast() != j){ //双端队列结构 while(!qmax.isEmpty() && arr[j] >= arr[qmax.peekLast()]){ qmax.pollLast(); } qmax.addLast(j); while(!qmin.isEmpty() && arr[j] <= arr[qmin.peekLast()]){ qmin.pollLast(); } qmin.addLast(j); } if(arr[qmax.peekFirst()] - arr[qmin.peekFirst()] > num){ break; } j++; } //以i开头一共j-i个,a[i..i]到a[i..j-1] result += (j - i); //开头i要自增,应该把队列中的i移除,只可能在最大和最小地方出现,要不就提前被弹出了 if(qmax.peekFirst() == i){ qmax.pollFirst(); } if(qmin.peekFirst() == i){ qmin.pollFirst(); } i++; } return result; } }
import java.util.*; import java.io.*; public class Main{ public static void main(String[] args){ Scanner sc=new Scanner(new BufferedInputStream(System.in)); int n=sc.nextInt(); int num=sc.nextInt(); int[] arr=new int[n]; for(int i=0;i<n;i++){ arr[i]=sc.nextInt(); } int[] min=new int[n]; int[] max=new int[n]; int minl=0; int minr=-1; int maxl=0; int maxr=-1; int i=0; int j=0; int res=0; while(i<n){ while(j<n){ while(minl<=minr&&arr[min[minr]]>=arr[j]) minr--; min[++minr]=j; while(maxl<=maxr&&arr[max[maxr]]<=arr[j]) maxr--; max[++maxr]=j; if(-arr[min[minl]]+arr[max[maxl]]>num){ break; } j++; } res+=j-i; if(max[maxl]==i) maxl++; if(min[minl]==i) minl++; i++; } System.out.println(res); } }
import java.util.*; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int num = sc.nextInt(); int[] arr = new int[n]; for(int i = 0; i < n; i++) { arr[i] = sc.nextInt(); } int res = getArrayNum(arr, num); System.out.println(res); } public static int getArrayNum(int[] arr, int num) { if(arr == null || arr.length == 0) return 0; LinkedList<Integer> qmax = new LinkedList<>(); LinkedList<Integer> qmin = new LinkedList<>(); int res = 0; int L = 0; int R = 0; while(L < arr.length) { while(R < arr.length) { while(!qmax.isEmpty() && arr[qmax.getLast()] <= arr[R]) qmax.removeLast(); qmax.add(R); while(!qmin.isEmpty() && arr[qmin.getLast()] >= arr[R]) qmin.removeLast(); qmin.add(R); if(arr[qmax.getFirst()] - arr[qmin.getFirst()] > num) break; R++; } res += R - L; if(qmax.getFirst() == L) qmax.removeFirst(); if(qmin.getFirst() == L) qmin.removeFirst(); L++; } return res; } }
import java.util.LinkedList; import java.util.Scanner; public class Main { public static int getNum(int[] arr, int num) { if (arr == null || arr.length == 0) return 0; LinkedList<Integer> qmin = new LinkedList<>(); LinkedList<Integer> qmax = new LinkedList<>(); int i = 0, j = 0, res = 0; while (i < arr.length) { // 求以arr[i]为开头,满足条件最长的子序列 while (j < arr.length) { if (qmin.isEmpty() || qmin.peekLast() != j) { while (!qmin.isEmpty() && arr[qmin.peekLast()] >= arr[j]) { qmin.pollLast(); } qmin.addLast(j); while (!qmax.isEmpty() && arr[qmax.peekLast()] <= arr[j]) { qmax.pollLast(); } qmax.addLast(j); } // 当不再满足题意,max(arr[i...j] - min(arr[i...j]) <= num 退出当前循环 if (arr[qmax.getFirst()] - arr[qmin.getFirst()] > num) break; j++; } // 以arr[i]为第一个元素的子数组,满足条件的j-i个 res += j - i; // 下一次从i+1开始,删除队列里不再框内的元素arr[i] if (qmin.peekFirst() == i) qmin.pollFirst(); if (qmax.peekFirst() == i) qmax.pollFirst(); i++; } return res; } public static void main(String args[]) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int num = sc.nextInt(); int[] arr = new int[n]; for (int i = 0; i < n; i++) { arr[i] = sc.nextInt(); } int res = getNum(arr, num); System.out.println(res); } }