文章目錄
- 題目描述
- 思路
- 代碼實現
題目描述
詳細描述:字節跳動2019春招研發部分編程題——萬萬沒想到之抓捕孔連順
輸入描述:
第一行包含空格分隔的兩個數字 N和D(1?≤?N?≤?1000000; 1?≤?D?≤?1000000)
第二行包含N個整數(取值區間為[0, 1000000])從小到大排列。從序列中提取所有數量為3的全組合,一個組合中 最大數-最小數 的差值必須 <= D。
輸出描述:
輸出滿足要求的排列數量
輸入例子1:
4 3
1 2 3 4
輸出例子1:
4
例子說明1:
可選方案 (1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)
輸入例子2:
5 19
1 10 20 30 50
輸出例子2:
1
例子說明2:
可選方案 (1, 10, 20)
思路
利用 雙指針構成滑動窗口 從而限定組合的區間,之后固定區間末尾的元素,對剩余數取 2 個進行組合。
邏輯說明:
在 [j, i]
的范圍里,當固定選 i
作為全排列中的一個元素,則剩下的兩個元素從 [j, i)
的范圍中組合(公式 C(i-j, 2)
),全部計算結果相加即為最終方案數。
舉例說明:
當給出的序列是 1,2,3,4,5 ;差值范圍為 3 時,滑動窗口第一次為 {1,2,3} ,固定 3 ,選取 (1,2) ,組成 (1,2,3)。
滑動窗口第二次為{1,2,3,4},固定 4 ,和前三個元素進行組合,可以組合成 (1,2,4)(1,3,4)(2,3,4)。
滑動窗口第三次為{2,3,4,5},之所以將 1 剔除是因為 5-1>3 超出差值范圍,固定 5 ,和前三個元素組合,可以組合成(2,3,5)(2,4,5)(3,4,5)
因此方案數共計:1+3+3=7
代碼實現
#include<iostream>
#include<vector>using namespace std;int main(){long long n, d;cin >> n >> d;vector<int> ivec(n);long long count = 0;for(int i = 0, j = 0; i < n; i++){ // i、j確定滑動窗口大小cin >> ivec[i];while(i>1 && ivec[i]-ivec[j] > d){ // 確定滑動窗口大小j++; // i>1時,滑動窗口里面的元素大于3個,此時要求max-min>d}count += (long long)(i-j)*(i-j-1)/2; // C(i-j, 2)公式// 本題的重點,等于固定 i 位,在 [j, i) 的范圍內組合兩個數和 i 位的數成一組}cout << count%99997867 << endl;return 0;
}