1. 程式人生 > 其它 >最大值減去最小值小於或等於 num 的子陣列數量問題

最大值減去最小值小於或等於 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();
  }
}

更多

演算法和資料結構筆記