组队(牛客)
写在前面:

今天跟彦祖和亦菲们分享另外一个秋招算法题 组队
题目如下:
描述
你的团队中有 n 个人,每个人有一个能力值 ai,现在需要选择若干个人组成一个团队去参加比赛,由于比赛的规则限制,一个团队里面任意两个人能力的差值必须要小于等于 k ,为了让更多的人有参加比赛的机会,你最多能选择多少个人参加比赛?
输入描述:
第一行一个整数 T,表示案例组数。
每个案例有两行:
第一行两个正整数 n,k,表示人的数量。
第二行n个以空格分隔的整数 ai ,表示每个人的能力值。
输出描述:
每个案例输出一行,表示可以参加比赛的最多人数。
示例1
输入:
1 5 3 8 3 5 1 6输出:
3说明:
选择能力值为 3,5,6 或者 5,6,8备注:
T≤10
1≤n≤2e5,1≤k≤1e9
1<=ai<=1e9

第一眼就感觉跟滑动窗口差不多 事实上也确实是
我们可以排个序,从小到大将元素放入双端队列队尾,若头尾差大于k,则去掉队头,记录最大的队伍元素个数即可。
代码如下:
C\C++版本:
#include<bits/stdc++.h> // 包含所有标准库头文件
using namespace std; // 使用标准命名空间
typedef long long ll; // 定义ll为long long类型别名
typedef pair<int, int>P; // 定义P为pair<int,int>类型别名const double eps = 1e-8; // 浮点数比较精度
const int NINF = 0xc0c0c0c0; // 负无穷大
const int INF = 0x3f3f3f3f; // 正无穷大
const ll mod = 1e9 + 7; // 模数
const ll maxn = 1e6 + 5; // 最大数组大小
const int N = 2e5 + 5; // 数组大小ll n, k, a[N]; // 全局变量:n(元素个数), k(最大差值), a(数组)void solve() {cin >> n >> k; // 输入n和kfor(int i = 1; i <= n; i++) {cin >> a[i]; // 输入数组元素}sort(a + 1, a + 1 + n); // 对数组排序(从索引1到n)queue<int> q; // 创建队列int ans = 0; // 记录最大满足条件的子数组长度for(int i = 1; i <= n; i++) {q.push(a[i]); // 将当前元素加入队列// 维护队列性质:队首和队尾差值不超过kwhile(q.back() - q.front() > k) {q.pop(); // 如果差值超过k,移除队首元素}// 更新最大长度ans = max(ans, (int)q.size());}cout << ans << "\n"; // 输出结果
}int main() {ios::sync_with_stdio(false); // 关闭C++与C的输入输出同步,提高速度cin.tie(0); // 解除cin与cout的绑定,提高速度int T; // 测试用例数量cin >> T;while (T--) { // 处理每个测试用例solve();}return 0;
}
Python版本:
import sys
from collections import dequedef solve():# 读取n和kn, k = map(int, sys.stdin.readline().split())# 读取数组arr = list(map(int, sys.stdin.readline().split()))# 对数组排序arr.sort()# 使用双端队列作为滑动窗口q = deque()ans = 0# 遍历每个元素for num in arr:# 将当前元素加入队列q.append(num)# 维护窗口性质:最大值-最小值 <= k# 由于数组已排序,队列中元素也是有序的while q[-1] - q[0] > k:q.popleft() # 移除队首元素(最小值)# 更新最大窗口大小ans = max(ans, len(q))print(ans)def main():# 读取测试用例数量T = int(sys.stdin.readline().strip())for _ in range(T):solve()if __name__ == "__main__":main()
Java版本:
import java.util.*;
import java.io.*;public class Main {// 快速输入类,提高Java输入效率static class FastReader {BufferedReader br;StringTokenizer st;public FastReader() {br = new BufferedReader(new InputStreamReader(System.in));}String next() {while (st == null || !st.hasMoreElements()) {try {st = new StringTokenizer(br.readLine());} catch (IOException e) {e.printStackTrace();}}return st.nextToken();}int nextInt() {return Integer.parseInt(next());}long nextLong() {return Long.parseLong(next());}}public static void solve() {FastReader sc = new FastReader();int n = sc.nextInt();int k = sc.nextInt();int[] arr = new int[n];for (int i = 0; i < n; i++) {arr[i] = sc.nextInt();}// 对数组排序Arrays.sort(arr);// 使用双端队列作为滑动窗口Deque<Integer> deque = new ArrayDeque<>();int ans = 0;// 遍历数组for (int num : arr) {// 将当前元素加入队列deque.offerLast(num);// 维护窗口性质:最大值-最小值 <= k// 由于数组已排序,队列中元素也是有序的while (deque.peekLast() - deque.peekFirst() > k) {deque.pollFirst(); // 移除队首元素(最小值)}// 更新最大窗口大小ans = Math.max(ans, deque.size());}System.out.println(ans);}public static void main(String[] args) {FastReader sc = new FastReader();int T = sc.nextInt();while (T-- > 0) {solve();}}
}
好啦差不多这么多了 其实思路很简单 如果我哪里没讲清楚有问题欢迎彦祖和亦菲们留言评论
读到这里,说明你已经成功Build了本文。为了不让你我之间的连接Timeout,不如点个关注建立长连接?你的每一个赞,都是我Ctrl + S的动力!
写在最后:


