問題
數(shù)組中有一個數(shù)字出現(xiàn)的次數(shù)超過數(shù)組長度的一半,請找出這個數(shù)字。
例如: 輸入一個長度為7的數(shù)組,
{1,2,2,2,5,4,2}
由于數(shù)字2在數(shù)組中出現(xiàn)了4次,超過數(shù)組長度的一半,因此輸出2。如果不存在則輸出0。
解答
首先說這是一道很經(jīng)典的面試題,很多互聯(lián)網(wǎng)公司都曾經(jīng)采用過這個題目。
下面是對該題的分析思路:
如果沒有時間復雜度的要求, 我們可以對數(shù)組進行排序,排序后的數(shù)組,那么我們只要遍歷一次就可以統(tǒng)計出每個數(shù)字出現(xiàn)的次數(shù),這樣也就能找出符合要求的數(shù)字。按照這個思路的時間復雜度是O(nlogn), 其中排序的時間復雜度是O(nlogn),遍歷的時間復雜度O(n)。
另一個思路是我們可以創(chuàng)建一個哈希表來消除排序的時間。哈希表的鍵值為數(shù)組中的數(shù)字,值為該數(shù)字對應的次數(shù)。有了這個哈希表之后,我們只需要遍歷數(shù)組中的每個數(shù)字,找到它在哈希表中對應的位置并增加它出現(xiàn)的次數(shù)。這種哈希表的方法在數(shù)組的所有數(shù)字都在一個比較窄的范圍內(nèi)的時候很有效。
最佳思路:數(shù)組中有一個數(shù)字出現(xiàn)的次數(shù)超過數(shù)組長度的一半,也就是說它出現(xiàn)的次數(shù)比其他所有數(shù)字出現(xiàn)次數(shù)的和還要多。
因此我們可以考慮在遍歷數(shù)組的時候保存兩個值:一個是數(shù)組中的一個數(shù)字,一個是次數(shù)。當我們遍歷到下一個數(shù)字的時候,如果下一個數(shù)字和我們之前保存的數(shù)字相同,則次數(shù)加1;如果下一個數(shù)字和我們之前保存的數(shù)字不同,則次數(shù)減1。
如果次數(shù)為0,我們需要保存下一個數(shù)字,并把次數(shù)置1。因為次數(shù)為0,表示前面是字符串計數(shù)抵消為0。
//Java源碼
public int MoreThanHalfNum_Solution(int [] numbers) {
int maxNum = 0;
if(numbers.length==0)
return maxNum;
maxNum = numbers[0];
int numCount = 1;
for(int i=1;i<numbers.length-1;i++){
if(numbers[i] == maxNum){
numCount++;
}else{
numCount--;
if(numCount == 0){
numCount = 1;
maxNum = numbers[i];
}
}
}
int total = 0;
for (int i = 0; i < numbers.length; i++) {
if (numbers[i] == maxNum) total++;
}
if (total * 2 <= numbers.length) {
return 0;
}
else return maxNum ;
}
上述源碼可以在 這里 調(diào)試