上篇博客讲到 2017年校招真题之倒置字符串 的三种解法,今天来介绍一下校招真题中的出现次数超过n/2的数的解法
2017年校招真题 出现次数大于n/2的数
题目描述
输入n个整数,输出出现次数大于等于数组长度一半的数。
输入描述:
每个测试输入包含 n个空格分割的n个整数,n不超过100,其中有一个整数出现次数大于等于n/2。
输出描述:
输出出现次数大于等于n/2的数。
示例1
输入 : 3 9 3 2 5 6 7 3 2 3 3 3
输出 : 3
解题思路
- 解法一
思路是通过unordered_map统计每个数出现的次数,再遍历unordered_map,找出出现次数超过数组大小一半的数,输出即可,有兴趣的读者可以参考博客 unordered_map/set的应用 有很多类似的题目
- 解法二
思路是将出现的数放入vector数组中,对数组进行排序,若是某个数出现次数超过了数组个数的一半,那么整个数组中间的那个数必然是该数,输出数组中间那个数即可。
- 解法三
O(n)思想:因为要找过半的数,用一个变量count记录读取每个变量变化的次数,一个变量temp记录可能过半的数,先让count=1,然后让temp=v [0],然后往后遍历一遍,碰到和temp相同的数就给count++,否则就count–,如果,count变成0,就让(vector数组遍历过程中的当前值),并让count=1,如此遍历一遍,因为有一个数过半,所以temp最后肯定存储的是过半的数
代码实现
- 解法一
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
int main()
{
int n;
vector<int> v;
while(cin >> n)
v.push_back(n);
unordered_map<int,int> countmp;
for(auto& e : v)
{
countmp[e]++;
}
for(auto& kv : countmp)
{
if(kv.second >= v.size()/2)
cout << kv.first << endl;
}
return 0;
}
- 解法二
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int n;
vector<int> v;
while(cin >> n)
v.push_back(n);
sort(v.begin(),v.end());
cout << v[v.size()/2 - 1] <<endl;
return 0;
}
- 解法三
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int n;
vector<int> v;
while(cin >> n)
v.push_back(n);
int count = 1,temp = v[0];
for(int i = 0;i < v.size();++i)
{
if(v[i] == temp)
count++;
else
count--;
if(count == 0)
{
temp = v[i];
count = 1;
}
}
cout << temp <<endl;
return 0;
}