構建二維數組法:時間和空間複雜度都大,不合題意。
先對數組排序,再取中間元素的方法,最快的排序算法時間複雜度爲O(logn),不合題意。
因此,需要採用其他的一些技巧實現。
方法一:由於目標數字,在數組中出現的次數超過一半。那麼,若每次都取出其中兩個不同的數,最後剩下的必然爲出現次數最多的數。
該方法避免排序,且時間複雜度爲O(n)。
#include <stdlib.h>
#include<iostream>
using namespace std;
int findMostAppear(int *a,int len)
{
int candidate=0;//候選點,作爲不同數字點對中的參考點
int count=0;//計數,若被選擇的點和參考候選點一樣,就+1;不一樣,-1;若該計數=0,重新選取候選點
for(int i=0;i<len;i++)
{
//若count爲0,說明沒有候選點,選擇一個候選點
if(count == 0)
{
candidate=a[i];
count=1;
}
//若count不爲0,說明有候選點,判斷a[i]是否和候選點一樣.若一樣,count++;若不一樣,count--,當count減到0的時候,重新選擇候選點
else
{
if(candidate == a[i] )
count++;
else
count--;
}
}
if (count==0)//判斷,若最後兩兩組隊,都沒有了(偶數組),則不存在超多次數一般的數
return -1;
else //else,存在超過一半的數,且就是最後留下的candidate值
return candidate;//最後剩的數就是要找的超過一半的數
}
int main()
{
int array[]={1,1,2,2,3,4,1,1};
int length=sizeof(array)/sizeof(array[0]);
int i=findMostAppear(array,length);
cout<<i<<endl;
getchar();
}
方法二:Hash法。
首先,構建hash_map,然後,遍歷數組,找到出現次數最大的關鍵字和其對應的最大次數,然後判斷該最大次數是否大於等於數組長度的一半,從而確定是否存在次數超過數組一半長度的數。
#include <hash_map>
#include <iostream>
using namespace std;
int findMostAppearHash(int *a,int len,int &val)
{
hash_map<int,int>myhash;
for (int i=0;i<len;i++)
{
if( ++myhash[a[i]] >= myhash[val] )
val =a[i];
}
//判斷最大次數是否大於數組長度一半
int count = myhash[val];
if (count>=(len+1)/2)
{
cout<<"找到超過數組一半的數"<<endl;
return val;
}
else
{
cout<<"不存在超過數組一半的數"<<endl;
return -1;
}
}
int main()
{
int array[]={1,1,2,2,3,4,1,1};
int length=sizeof(array)/sizeof(array[0]);
int value=0;
int i=findMostAppearHash(array,length,value);
cout<<i<<endl;
getchar();
}
方法三:使用兩個變量A和B。
其中A存儲某個數組中的數,B用來計數。開始時候講B初始化爲0,然後遍歷數組。
若當前數與A不同,判斷:若B=0,則A=當前數; 若B>0,則B=B-1。
若當前數與A相同,B計數加1。
遍歷結束,A中存儲的數就是所要找的數。該算法時間複雜度爲O(n), 空間複雜度爲O(1)。