字节真题:万万没想到之抓捕孔连顺
牛客链接: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 }
心之所愿,永不相忘