https://www.cnblogs.com/gczr/p/8334459.html
来看这样一个例子:
5 1 5 4 1 1 3 1 2 1 1
一共11个数字,其中1一共出现了6次。那么如何快速的找到这个6呢?我们来考虑这样一个现实生活中的例子:有一群人在打群架,他们每个人有一个编号,代表自己所处的势力,现在这一群人按照顺序依次往广场中央走,如果广场内现在有和自己不是一个势力的人,那么他就和其中一个同归于尽,问,最后哪一个势力的人会获胜?我们按照这个意思,再来看一下刚才这个例子:
1)势力5的一个人走进广场中央,现在广场中央有一个人,势力是5
2)势力1的一个人走进广场中央,他发现广场中央有一个势力是5的人,于是同归于尽,现在广场上没有人
3)势力5的一个人走进广场中央,现在广场中央有一个人,势力是5
4)势力4的一个人走进广场中央,他发现广场中央有一个势力是5的人,于是同归于尽,现在广场上没有人
5)势力1的一个人走进广场中央,现在广场有一个人,势力是1
6)势力1的一个人走进广场中央,现在广场有两个人,势力是2
……
可以发现,每一次火拼,势力最大(也就是出现次数最多的那个数字)的那个每次最多只会死亡一个。而火拼最多会进行N/2次,出现频率最高的那个数字最多只会损失N/2个,而题上告诉我们出现次数已经超过了一半,因此广场上剩下的那个团伙的编号必然是出现次数做多的那个!
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int findPossibleMain(int A[], int n) {//找出最大势力
int x = 1;//开始广场上有一个人
int main = A[0];//这个人的势力是A[0]
for (int i = 1; i < n; i++) {//每一轮各个势力派一人上广场PK
if (x == 0)
{ //广场没人,此势力占领广场,人数为1
main = A[i];
x = 1;
}
else
{
if (main==A[i])
{
x++;//广场上的势力和进场势力同属一个,人数加1
}
else //火拼的次数最多为n/2,每次火拼主势力最多损失1人(损失0人是此场火拼主势力没参与)
{
x--;//不同势力,火拼后同归于尽
}
}
}
return main;
}
int main() {
//int A[maxn]={0,5,5,3,5,7,5,5};
//int A[maxn] = { 0,5,5,3,5,1,5,7 };
int n,A[100];
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
scanf("%d", &A[i]);
}
int main = findPossibleMain(A, n);//可能的主元素
printf("%d\n", main);
int x = 0;//可能的主元素出现的次数
for (int i = 0; i < n; i++)
{
if (A[i] == main)
{
x++;
}
}
if (x > n / 2)
{
printf("所求的元素:%d" , main);
}
else
{
printf("没有这样的元素");
}
return 0;
}