剑指offer28_数组中出现次数超过一半的数字_题解
数组中出现次数超过一半的数字
题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
示例1
输入
[1,2,3,2,2,2,5,4,2]
返回值
2
分析
方案一:哈希
先遍历一遍数组,在map中存每个元素出现的次数,然后再遍历一次数组,找出众数。
代码
/**
时间复杂度:O(N)
空间复杂度:O(N)
**/
class Solution
{
public:
int MoreThanHalfNum_Solution(vector<int> numbers)
{
unordered_map<int, int> mp;
for (const int val : numbers)
{
mp[val]++;
}
for (const int val : numbers)
{
if (mp[val] > numbers.size() / 2)
return val;
}
return 0;
}
};
方案二:排序
将数组排序,众数一定在数组中间,再判断众数出现的次数是否超过数组长度的一半
代码
/**
时间复杂度:O(nlogn)
空间复杂度:O(1)
**/
class Solution
{
public:
int MoreThanHalfNum_Solution(vector<int> numbers)
{
sort(numbers.begin(), numbers.end());
int cond = numbers[numbers.size() / 2];
int votes = 0;
for (const int k : numbers)
{
if (cond == k)
++votes;
}
if (votes > numbers.size() / 2)
return cond;
return 0;
}
};
方案三:摩尔投票法
假设数组首个元素为众数,遍历并统计票数。当发生票数和 = 0时,剩余数组的众数一定不变
算法流程:
- 初始化: 票数统计 votes = 0 , 众数 x;
- 循环: 遍历数组 nums 中的每个数字 num ;当 票数 votes 等于 0 ,则假设当前数字 num 是众数;
- 当 num = x 时,票数 votes 自增 1 ;当 num != x 时,票数 votes 自减 1 ;
- 返回值: 返回 x 即可;
代码
class Solution
{
public:
int MoreThanHalfNum_Solution(vector<int> numbers)
{
int cond = -1; //众数cond
int votes = 0; //票数votes
for (int i = 0; i < numbers.size(); ++i)
{
// 当票数votes等于0时,假设当前数字num是众数,投票数+1
if (votes == 0)
{
cond = numbers[i];
++votes;
}
else
{
// 当num=cond时,票数votes++
if (cond == numbers[i])
++votes;
// 当num!=cond时,票数votes--
else
--votes;
}
}
votes = 0;
//验证x是否为众数
for (const int k : numbers)
{
if (cond == k)
++votes;
}
if (votes > numbers.size() / 2)
return cond;
return 0;
}
};