主要元素
使用分治策略求出序列中的众数
思路
- 划分:从中间的元素进行划分,找出该元素左右两边与中间数字相同的起始与终止界限
- 解决:根据左右界限计算众数的个数
- 合并:当左右剩余元素数量大于当前众数的个数,进行回溯
递归体:划分众数,并根据划分计算众数的个数
递归边界:当左右剩余元素数量小于当前众数的个数,不再递归,递归结束
代码
求众数代码,非leetcode代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 10005;
int n;
int arr[maxn];
map<int, int> mp;
//s序列,长度为n,左右两边与中间数字相同的起始与终止界限
void split(int s[], int n, int &l, int &r)
{
int mid = n / 2;
//起始点l与终止点r之差即为s[mid]的个数
for(l = 0; l < n; ++l)
{
if(s[l] == s[mid])
break;
}
for(r = l + 1; r < n; ++r)
{
if(s[r] != s[mid])
break;
}
}
//mid众数,maxCnt为重数,序列s,长度n
void getMode(int &mid, int &maxCnt, int s[], int n)
{
int l, r;
split(s, n, l, r);
int index = n / 2; //众数下标
int cnt = r - l; //重数
if(cnt > maxCnt)//比当前众数多
{
maxCnt = cnt;
mid = s[index];
mp.clear();
mp[mid] = maxCnt;
}
else if(cnt == maxCnt)
{
mid = s[index];
mp[mid] = maxCnt;
}
//l表示mid左边的长度,长度大于maxCnt才有必要搜索
if(l >= maxCnt)
{
getMode(mid, maxCnt, s, l);
}
//n-r表示mid右边的个数,右边数组的起始地址变更为arr + r
if(n - r >= maxCnt)
{
getMode(mid, maxCnt, s + r, n - r);
}
}
void display(){
for (int i = 0; i < n; ++i){
printf("%d ", arr[i]);
}
printf("\n");
}
int main(int argc, char *argv[]) {
printf("input n:");
scanf("%d", &n);
srand((unsigned)time(NULL)); //随机种子
for(int i = 0; i < n; ++i)
{
arr[i] = (int)(round(1.0 * rand() / RAND_MAX * n));//生成0~n的随机数
}
display();
//要进行排序的,否则有些特殊情况无法AC
sort(arr, arr + n);
display();
int maxCnt = 0;//重数
int mode = 0; // 众数
getMode(mode, maxCnt, arr, n);
int sum = 0;
for(auto it = mp.begin(); it != mp.end(); ++it)
{
sum += it->second;
}
if(sum == n)
{
cout << "没有众数" << endl;
}
else
{
for(auto it = mp.begin(); it != mp.end(); ++it)
{
cout << "众数:" << it->first << " 重数:"<< it->second << endl;
}
}
system("pause");
return 0;
}
//特殊样例
7
2 2 1 1 1 2 2
ans: 众数:2,重数:4
map映射
class Solution {
public:
unordered_map<int, int> mp;
int maxn = 0;
int mode = 0;
int majorityElement(vector<int>& nums) {
for(auto num: nums){
mp[num] += 1;
if(mp[num] > maxn){
maxn = mp[num];
mode = num;
}
}
if(maxn > nums.size() / 2){
return mode;
}
return -1;
}
};
摩尔投票法,满足时间:O(N),空间O(1)
摩尔投票法,也称同归于尽法,用于求数量超过半数的元素。
元素两两厮杀,元素不同则进行碰撞抵消,元素相同则对count进行累加,最后剩下的major即为众数
b站视频
class Solution {
public:
//摩尔投票法
int majorityElement(vector<int>& nums) {
//找众数
int count = 0;
int major = nums[0];
for(auto num:nums){
if(major == num){
count++;
}else{
count--;
}
if(count < 0){
major = num;
count = 0;
}
}
//判断众数的个数是否符合要求
count = 0;
for(auto num:nums){
if(num == major){
count++;
}
}
if(count > nums.size() / 2){
return major;
}
return -1;
}
};