作者:Grey
原文地址:
博客园:最大值减去最小值小于或等于 num 的子数组数量问题
CSDN:最大值减去最小值小于或等于 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]中的最小值。
牛客-最大值减去最小值小于或等于 num 的子数组数量
本题可以用滑动窗口算法来解,算法说明见:滑动窗口最大值问题
根据题目意思,我们可以得到如下三个结论
第一个结论:arr[L..R]达标,则 arr 中内部的任何一个子数组都达标;
第二个结论:arr[L..R]不达标,则 arr 扩充后肯定也不达标;
第三个结论:L...R 范围如果达标,其子数组个数为:R - L。
利用滑动窗口算法,我们可以得到必须以l位置作为左边界的情况下,有多少达标的数组。
完整代码如下(含对数器)
import java.util.LinkedList;
import java.util.Scanner;public class Main {public static int getNum(int[] arr, int num) {LinkedList qMax = new LinkedList<>();LinkedList qMin = new LinkedList<>();int ans = 0;int l = 0;int r = 0;while (l < arr.length) {while (r < arr.length) {while (!qMax.isEmpty() && arr[qMax.peekLast()] <= arr[r]) {qMax.pollLast();}qMax.addLast(r);while (!qMin.isEmpty() && arr[qMin.peekLast()] >= arr[r]) {qMin.pollLast();}qMin.addLast(r);if (arr[qMax.peekFirst()] - arr[qMin.peekFirst()] > num) {break;}r++;}// r是以l作为左边界,第一个不满足条件的位置ans += (r - l);// 弹出过期位置if (!qMax.isEmpty() && qMax.peekFirst() == l) {qMax.pollFirst();}// 弹出过期位置if (!qMin.isEmpty() && qMin.peekFirst() == l) {qMin.pollFirst();}l++;}return ans;}public static void main(String[] args) {Scanner in = new Scanner(System.in);int n = in.nextInt();int m = in.nextInt();int[] arr = new int[n];for (int i = 0; i < n; i++) {arr[i] = in.nextInt();}System.out.println(getNum(arr,m));in.close();}
}
算法和数据结构笔记
上一篇:aws cdk 创建eks集群和ecs集群并部署服务
下一篇:科利莫尔:FIFA要求“必须”公布准确首发阵型,但主帅经常没遵守 科利莫尔:FIFA要求“必须”公布准确首发阵型,但主帅经常没遵守