最大值減去最小值小於或等於 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]
中的最小值。
思路
本題可以用滑動窗口算法來解,算法說明見:滑動窗口最大值問題
根據題目意思,我們可以得到如下三個結論
第一個結論: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();
}
}