最好一样
题目描述
时间限制:C/C++语言 1000MS;其他语言 3000MS
内存限制:C/C++语言 131072KB;其他语言 655360KB
题目描述: 给出一个序列包含 n 个正整数的序列 A,然后给出一个正整数 x,你可以对序列进行任意次操作的,每次操作你可以选择序列中的一个数字,让其与 x 做按位或运算。你的目的是让这个序列中的众数出现的次数最多。
请问众数最多出现多少次。
输入
输入第一行仅包含两个正整数 n 和 x,表示给出的序列的长度和给定的正整数。(1<=n<=100000,1<=x<=1000)
接下来一行有 n 个正整数,即这个序列,中间用空格隔开。(1<=a_i<=1000)
输出
输出仅包含一个正整数,表示众数最多出现的次数。
样例输入
5 2
3 1 3 2 5
样例输出
3
提示
样例解释
例如如果序列中所有数字都不修改时,众数为 3,3 出现的次数为 2,如果我们把1 都做如题操作,序列会变为 3,3,3,2,5,此时众数为 3,出现次数为 3,所以我们选择后者方案,输出众数出现的次数,即 3。
解题思路
这道题看起来有点绕,但是想清楚之后就知道可以分为两步解决这个问题:
- 首先将x与序列的所有数做一次或运算(这样众数个数才是最多的)
- 求新序列的众数出现的次数
代码如下:
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
int getNum(int a[], int n)
{
unordered_map<int, int> myMap;
int MaxNum = 0;
for(int i = 0; i < n; i ++)
{
myMap[a[i]] ++;
}
for(auto i = myMap.begin(); i != myMap.end(); i ++)
{
if(i -> second > MaxNum)
{
MaxNum = i -> second;
}
}
return MaxNum;
}
int main()
{
int n, x;
int a[100000];
cin >> n >> x;
for(int i = 0; i < n; i ++)
{
cin >> a[i];
}
for(int i = 0; i < n; i ++)
{
a[i] = a[i] | x;
}
cout << getNum(a, n);
return 0;
}
求数组中众数及其出现次数的方法有很多,我之前习惯用一个新数组的索引表示原数组的值,用新数组的值表示对应索引的数字在原数组中出现的次数,但是这种方式存在明显的缺点:
- 大量数组空间空闲
- 新数组的长度受制于原数组中的最大值
- 当原数组中存在负数时该方法失效
推荐使用哈希表的键值对来储存原数组中的数字及其出现的次数,C++11中的unordered_map可以很好的胜任众数相关的问题。