菜鸟有话说
这里推荐大家去看官方题解,本题解是为了记录一些没用过的知识点,复习使用,看过复习请点击此处
题目分析
由于每一个数字都会增加,利用贪心的思维,我们就不难发现,想要让这个没什么规律的数组中出现大量相同的数字,就必须要排序,在一个区间中去寻找
这么说有点抽象,我们举个例子来看,1 2 3 4 5 6 , 这六个数字要是想要有最多数量的相同数字,那么数列肯定是6 5 4 3 2 1
打乱呢?
由于本题没有这些数字位置上的限制, 1 6 4 5 3 2也可以先排序,然后再用相同的数列求解
可以数字不一定这么有规律,那么想到这应该就明白了,没错,由于不需要让所有的数字都符合条件,排好序的数组中肯定是有一个区间内可以用1~n中不重复的数字可以获得等同于区间长度的相同数字个数
那么怎么来寻找这个区间呢?或者说这个区间应该符合哪些条件
我们通过观察发现,区间内的数字最大差一定不小于 1 并且 不超过n-
1,并且这是个排好序的数组,区间内的数字之间的差也一定符合这个范围(一定小心注意相同的数字,相同的数字只能算一次,就这个需要特别判断一下),所以我们只需要对排好序数组找到其中符合条件的最大的区间
算法和技巧总结
那么寻找区间大概率能想到双指针算法
写这篇的主要目的是为了这个去重函数,由于差值不能等于0,所以不需要重复的元素,但是使用set需要用迭代器,这就比较的麻烦了,不够熟练的话容易出错,这里就要使用vector<int>的unique函数,非常的好用,这里注意一下,它的去重不是erase删除,而是把重复的元素都放到后边了,还需要一步来resize重新构造数组的大小,以便于后序使用
总代码
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int n,t;
int main()
{
cin >> t;
while (t--){
cin >> n;
vector<int> a(n);
for(int i=0;i<n;i++) cin >> a[i];
sort(a.begin(),a.end());
a.resize(unique(a.begin() , a.end()) - a.begin());
int ans = 0;
for(int i=0,j=0;i<a.size();i++){
while (a[i] - a[j] >= n){
j ++;
}
ans = max(ans, i - j + 1);
}
cout << ans << endl;
}
}