最大值减去最小值小于或等于 num 的子数组数量问题

最大值减去最小值小于或等于 num 的子数组数量问题

作者: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<Integer> qMax = new LinkedList<>();
    LinkedList<Integer> 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();
  }
}

更多

算法和数据结构笔记

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GreyZeng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值