题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
题解思路
方法一:排序
- 对数组进行排序
- 数字出现频率超一半的,一定是数组的中位数
- 但是数组的中位数不一定是频率出现最高的数,需要判断一下这个数字出现的频率是否超过整个数组长度的一半
- 如果这个数字出现频率超过数组长度的一半,则找到这个数字;否则没有这个数字,返回0
C代码如下:
//快速排序算法
void quickSort(int * a, int left, int right){
int i, j, tmp, t;
if (left > right){
return;
}
tmp = a[left];
i = left;
j = right;
while (i != j){
while (a[j] >= tmp && i < j) --j;
while (a[i] <= tmp && i < j) ++i;
if(i < j){
t = a[i];
a[i] = a[j];
a[j] = t;
}
}
a[left] = a[j];
a[j] = tmp;
quickSort(a, left, j - 1);
quickSort(a, j + 1, right);
}
//数组再经过排序后,数字出现频率超一半的,一定是数组的中位数
int checkMoreThanHalf(int * arr){
int len = sizeof(arr) / sizeof(arr[0]);
quickSort(arr, 0, len - 1);
int mid = len / 2;
int result = arr[mid];
if (!checkIsMoreThanHalf(arr, result, len))
{
result = 0;
}
return result;
}
//判断一下这个数字出现的频率是否超过整个数组长度的一半
int checkIsMoreThanHalf(int * arr, int result, int len){
int i;
int count = 0;
for (i = 0; i < len; i++){
if (arr[i] == result)
++count;
}
if (count >(len - 1) / 2)
return 1;
else
return 0;
}
C++代码题解
class Solution {
public:
int majorityElement(vector<int>& nums) {
sort(nums.begin(), nums.end());
int num = nums[nums.size()/2];
if(nums.size()/2 < count(nums.begin(), nums.end(), num)){
return num;
}
return 0;
}
};
方法二:哈希表
这个方法最简单,用哈希表记录每个数字出现的次数,最后看哪个数字次数超过一半就行了。
时间复杂度 O(n) ,空间复杂度 O(n) 。
代码实现:
class Solution {
public:
int majorityElement(vector<int>& nums) {
int n = nums.size();
unordered_map<int, int> mp;
for (auto x : nums) mp[x]++;
for (auto [k, v] : mp) {
if (v > n/2) return k;
}
return 0;
}
};
方法三:摩尔投票
这个方法我一开始也想到了,但是没有想到这竟然有理论解释,而且是大名鼎鼎的摩尔投票算法。
它的主要步骤是这样的:
- 初始化两个变量, cand 表示候选人,cnt 表示赞同它的票数。
- 如果 cnt = 0,那么 cand 就设置为当前的数字。
- 如果 cand 等于当前数字,那么票数 cnt 加一,否则票数减一。
- 最后 cand 就是得票超过一半的众数。
代码实现:
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> v) {
int num = v[0], count_i = 1;
for(int i = 1; i < v.size(); i++){
if(v[i] == v[i-1]) count_i++;
else {
if(count_i <= 1) num = v[i];
else count_i--;
}
}
if (v.size() / 2 < count(v.begin(), v.end(), num)) return num;
return 0;
}
};