package algorithm;
import java.util.LinkedList;
/**
* 程序员代码代码面试指南:最大值减去最小值小于或者等于num的子数组数量
* 1.变量
* qmax:LinkedList<Integer>,用来实现子数组的最大值,队头为当前子数组的最大值
* qmin:LinkedList<Integer>,用来实现子数组的最小值,队头为当前子数组的最小值
* result:int,统计符合条件的子数组数量
* 2.对输入进行校验
* arr不为空,且长度大于0
* 3.双重遍历
* i,j为arr数组下标,i=0,j=i
* j向右移动,到数组尽头完成一次遍历,j++,j<arr.length
* i向右移动,i++,j再进行一次遍历
* i移动到数组尽头,遍历结束,i<arr.length
* 4.数组下标入队
* 入队的下标为j
* j进入qmax之前先进行循环判断,如果队尾元素小于或者等于arr[j],则要先弹出,直到没有比他小的元素再入队:!qmax.isEmpty()&&qmax.peekLast()<=arr[j]
* j进入qmin之前先 进行循环判断,如果队尾元素大于或者等于arr[j],则要先弹出,直到没有比他大的元素再入队:!qmin.isEmpty()&&qmin.peekLast()>=arr[j]
* 5.统计符合条件的子数组数量
* 判断qmax和qmin的队头元素是否满足条件,满足则result++:qmax.peekFirst() - qmin.peekFirst() <= num
* 6.清除无效下标
* 如果队头元素不在范围就出队:qmax.peekFirst() < i || qmax.peekFirst() > j,qmin.peekFirst() < i || qmin.peekFirst() > j
*/
public class SubarrayNum {
/**
* 最大值减去最小值小于或者等于num的子数组数量
* @param arr 原数组
* @param num 要比较的值
* @return 符合条件的字数组数量
*/
public static int getNum(int[] arr, int num) {
LinkedList<Integer> qmax = new LinkedList<>();
LinkedList<Integer> qmin = new LinkedList<>();
int result = 0;
if (arr.length == 0 || arr == null) {
return 0;
}
for (int i = 0; i < arr.length; i++) {
for (int j = i; j < arr.length; j++) {
while (!qmax.isEmpty() && qmax.peekLast() <= arr[j]) {
qmax.pollLast();
}
qmax.addLast(j);
while (!qmin.isEmpty() && qmin.peekLast() >= arr[j]) {
qmin.pollLast();
}
qmin.addLast(j);
if (qmax.peekFirst() - qmin.peekFirst() <= num) {
result++;
}
if (qmax.peekFirst() < i || qmax.peekFirst() > j) {
qmax.pollFirst();
}
if (qmin.peekFirst() < i || qmin.peekFirst() > j) {
qmin.pollFirst();
}
}
}
return result;
}
/**
* 测试
* @param args
*/
public static void main(String[] args) {
int[] arr = {3, 5, 7, 8, 6, 2};
System.out.println(getNum(arr, 5));
}
}