字节真题:万万没想到之抓捕孔连顺

牛客链接:https://www.nowcoder.com/question/next?pid=16516564&qid=362290&tid=49703321

直接上代码,记录下我的做题经过

 1 // 应该至少需要3个while循环
 2 // 第一个循环:固定第一个特工位置,另外两个特工往右找
 3 // 第二个循环:固定第二个特工位置,如果与第一个特工保持在最大范围内,向右招最后一个特工,否则,返回第一个循环第一个特工位置右移
 4 // 第三个循环:如果与第一个特工的位置超过最大范围,返回第一个循环(不用和第二个特工位置做比较)
 5 // 结果,通过了2/10的用例,出现超时问题
 6 
 7 // 第二种优化方法:时间复杂度O(n)
 8 // 第一个循环:固定第一个特工位置
 9 // 第二个循环,不断往后找第三个特工位置,直到其位置超出最大距离,根据两个位置的索引,得到区间内元素的个数
10 // 假设元素个数为x,那么这个区间内可选的方案数为:C(x,3)
11 // 结果,通过了2/10的用例,未出现超时问题
12 
13 // 第三种方法:时间复杂度O(n)
14 // 第二种方法方向是正确的,但没考虑仔细,比如:1 2 3 4 5 6 最大距离为4;当ridx指向6时,fidx指向4,少了2 3 6和 2 4 6的组合
15 // 看了下题解,应该固定第一个特工,其位置不断向右滑动,这样每个区间都是独立的,如第一个区间一定包括1,后面的区间一定不包括1
16 // 每个区间区C(x,2)
17 #include<iostream>
18 #include<vector>
19 using namespace std;
20 
21 #define MAX_VAL 99997867
22 
23 long long getRes(vector<long long>init, long long k) {
24     long long res = 0;
25     long long fidx = 0, ridx=2;
26     long long len = init.size();
27     while (fidx < len - 2) {
28         // ridx = fidx + 2;   // 后面的指针不需要往回缩了
29         while (ridx < len && (init[ridx] - init[fidx]) <= k) {
30             ridx++;
31         }
32         // ridx指向范围区间的下一个,计算c(ridx-1-fidx,2)
33         long long tmp = ridx -1- fidx;
34         res = (res+(tmp - 1) * tmp / 2)%MAX_VAL;
35         fidx++;          // 第一个特工右移
36     }
37     return res % MAX_VAL;
38 }
39 
40 int main() {
41     long long d, k;
42     cin >> d >> k;
43     vector<long long> init;
44     for (long long i = 0; i < d; ++i) {
45         long long tmp;
46         cin >> tmp;
47         init.push_back(tmp);
48     }
49     long long res = getRes(init, k);
50     cout << res;
51     return 0;
52 }
心之所愿,永不相忘
原文地址:https://www.cnblogs.com/zgll/p/15500943.html