最大值減去最小值小於或等於 num 的子陣列數量問題
阿新 • • 發佈:2022-12-08
最大值減去最小值小於或等於 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(); } }