牛客小白月赛117 D题
D题求众数可以用排序去解决,排序要两个要求:1.按出现次数从大到小排序(示例1);2.如果出现次数相同,按数字从大到小排序(示例2)。
我参考了一个大神的AC代码,代码用STL的sort做排序。其中的cmp函数我学到了东西:
变量说明:
a,b:输入的数字
num[a]:数字a出现的次数
num[b]:数字b出现的次数
若num[a]==num[b]则比较a和b谁大,return a>b; 否则return num[a]>num[b]。
bool cmp(int a,int b){
if(num[a]==num[b]) return a>b;
else return num[a]>num[b];
}
除了排序外,我还看了一下解题思路:
这道题的数字存在数组v中,出现次数存在num数组中,用数组b(类似于集合),存储出现过的次数。在输入数据后,我们用cmp函数对b数组元素按照从大到小排序。
题目操作中v[i],v[j],v[j]-1,v[i]+1这四项的出现的次数会影响最终结果。我们用双重循环枚举其中的i,j且要满足i!=j。拿到满足条件的i和j,我们就去更新一下num数组对应的下标,在这里我们考虑b数组的前4项,以及次数增加的i+1和j-1,把它们加进数组w中,我们之后对w数组按照cmp函数进行排序。排序后,第一位的元素是这组数的众数。
为什么是前四项?
因为题目操作主要涉及v[i],v[j],v[j]-1,v[i]+1,假设前四项就是这四项,那通过操作有可能排在2,3,4位的项会来到第一。
完整AC代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int num[N];
bool cmp(int a,int b){
if(num[a]==num[b]) return a>b;
else return num[a]>num[b];
}
void work(){
int n;
cin>>n;
vector<int> v(n);
vector<int> b;
for(int i=0;i<n;i++){
cin>>v[i];
num[v[i]]++;
if(num[v[i]]==1){
b.push_back(v[i]);
}
}
sort(b.begin(),b.end(),cmp);
set<int> ans;
int m=v.size();
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(i==j) continue;
int x=v[i],y=v[j];
num[x]--,num[y]--;
num[x+1]++,num[y-1]++;
vector<int> w;
for(int k=0;k<min(m,3);k++) w.push_back(b[k]);
w.push_back(x+1),w.push_back(y-1);
sort(w.begin(),w.end(),cmp);
ans.insert(w[0]);
num[x]++,num[y]++;
num[x+1]--,num[y-1]--;
}
}
set<int>::iterator it=ans.begin();
for(it=ans.begin();it!=ans.end();it++) cout<<*it<<" ";
}
int main(){
work();
return 0;
}