1. 程式人生 > 其它 >n個整型元素的陣列a,找出出現次數超過n / 2的元素

n個整型元素的陣列a,找出出現次數超過n / 2的元素

技術標籤:# 演算法題

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;
}