178-找出陣列中出現次數超過一半的數
阿新 • • 發佈:2021-02-08
題目如下:
給定一個數組,陣列中有一個元素長度超過了整個陣列的一半。
例如[1, 1, 2, 1, 5] 輸出:1
要求在O(N)的時間複雜度內,且空間複雜度O(1)
解題思路
士兵佔領法則
演算法思想如下,假設沒個數字都代表一個隊伍的士兵編號,那麼題目可以轉化為,有N個隊伍的士兵,但是有一個隊伍的士兵數量超過了總數的一半。
以下用佔領山頭的方式來求解:
1、用一個指標來遍歷士兵陣列
2、如果是一個空山頭的話,那麼直接將這個士兵放在山頂,表示這個隊伍佔領。
3、接下來進行遍歷,如果下一個來的是同樣編號隊伍的士兵,那麼隊伍壯大,繼續佔領。
4、如果不是一個編號隊伍的士兵,那麼新的士兵和佔領山頭隊伍的士兵(一個士兵)同歸於盡。這裡的同歸於盡是指一個對一個
最後還留在山頭的,一定是哪個超過一半人數的隊伍。
程式碼實現加註釋如下
#include<stdio.h>
int MoreThanHalfNum_Solution(int *arr,int len)
{
//士兵佔領法
if (len == 0)
{
return 0;
}
if (len == 1)
{
return arr[0];
}
int count = 0;//初始化計數值為0
int index = -1; //初始化當前的士兵的代表值
for (int i=0;i<len; ++i)//遍歷陣列
{
if(count == 0)//如果計數為0,進入此語句
{
count++;//計數值為1
index =arr[i];//將此時的值賦值給士兵代表的值
continue;//提前進入下一次迴圈
}
if (arr[i] == index)//如果值和士兵代表的值相同,進入此語句
{
count++;//計數值加1
}
else//值和士兵的值不同
{
count-- ; //進行同歸於盡
}
}
count = 0;//重置為0
for (int i=0;i<len;++i)//遍歷陣列
{
if (arr[i] == index)
{
count++;//記錄最後存活的士兵的原有隊伍的人數
}
}
return count * 2 > len ? index : 0;
//如果最後存活的士兵的原有隊伍人數超過總數的一半返回士兵代表的值
//否則返回0
}
int main()
{
int arr[]={1,1,2,1,5};
int len=sizeof(arr)/sizeof(arr[0]);
printf("%d\n",MoreThanHalfNum_Solution(arr,len));
return 0;
}
執行截圖如下: