題目:陣列中有乙個數字出現的次數超過了陣列長度的一半,找出這個數字。
分析:
1,如果無序,是不是可以先把陣列中所有這些數字進行排序,最常用的快速排序o(n*logn)即可。然後把那個出現次數超過一半的數字直接輸出,題目便解答完成了。總的時間複雜度為o(n*logn)。
乙個數字在陣列中的出現次數超過了一半,那麼在已排好序的陣列索引的n/2處(從零開始編號),就一定是這個數字。自此,我們只需要對整個陣列排完序之後,然後直接輸出陣列中的第n/2處的數字即可,這個數字即是整個陣列中出現次數超過一半的數字,總的時間複雜度縮小到o(n*logn)。
2,既要縮小總的時間複雜度,那麼就用查詢時間複雜度為o(1),事先預處理時間複雜度為o(n)的hash表。
雜湊表的鍵值(key)為陣列中的數字,值(value)為該數字對應的次數。然後直接遍歷整個hash表,找出每乙個數字在對應的位置處出現的次數,輸出那個出現次數超過一半的數字即可。
3,如果每次刪除兩個不同的數(不管是不是我們要查詢的那個出現次數超過一半的數字),那麼,在剩下的數中,我們要查詢的數(出現次數超過一半)出現的次數仍然超過總數的一半。通過不斷重複這個過程,不斷排除掉其它的數,最終找到那個出現次數超過一半的數字。這個方法,免去了上述思路
一、二的排序,也避免了思路三空間o(n)的開銷,總得說來,時間複雜度只有o(n),空間複雜度為o(1),不失為最佳方法。
4, 陣列中有個數字出現的次數超過了陣列長度的一半。也就是說,有個數字出現的次數比其他所有數字出現次數的和還要多。
因此我們可以考慮在遍歷陣列的時候儲存兩個值:乙個是陣列中的乙個數字,乙個是次數。當我們遍歷到下乙個數字的時候,如果下乙個數字和我們之前儲存的數字相同,則次數加1。 如果下乙個數字和我們之前儲存的數字不同,則次數減1。如果次數為零,我們需要儲存下乙個數字,並把次數重新設為1。
int find(int a,int n)
else
else}}
return temp;}/*
有幾個問題,還是需要我們注意:
(1)當輸入無效性時,要處理。比如陣列長度為0。
(2)最後,上述**加了乙個判斷,如果陣列中並不包含這麼乙個數字,那麼輸入也是無效的。因此在函式結束前還加了一段**來驗證輸入是不是有效的。
*/
修正後:
//修正2
bool input=true;
int find(int a,int n)
int temp=0;
int cnt=0;
int i=0;
for(i=0;iif(cnt==0)
else
else}}
//修正2
intsum=0;
for(i=0;iif(temp==a[i])
}if(2*sum
<=n)
return temp;
}
參考部落格: 面試題29 陣列中出現次數超過一半的數字
題目 陣列中有乙個數字出現的次數超過陣列長度的一半,請找出這個數字。例如輸入乙個長度為9的陣列。由於數字2在陣列中出現了5詞,超過陣列長度的一半,因此輸出2.思路 1,如果對陣列排序,那麼n 2對應的數一定是超過一半的數字 前提是存在這個數字 即長度為n的陣列中第n 2大的數字,o n 2,根據陣列...
面試題25 陣列中出現次數超過一半的數字
方法一 先對陣列進行排序 再遍歷排序後的陣列,統計每個數 的次數 出現次數最大的數即為要找的數。時間複雜度 o nlogn o n o nlogn 不需要額外儲存空間 方法二 先對陣列進行排序 出現次數超過陣列長度的一半的數必然是 陣列中間的那個數 時間複雜度o nlgn o 1 o nlgn 不需...
面試題29 陣列中出現次數超過一半的數字
面試題29 陣列中出現次數超過一半的數字 題目 陣列中有乙個數字的出現次數超過了陣列長度的一半,找出這個數字。常規的演算法是先對陣列排序,排序的時間複雜度是o nlogn 如果和之前儲存的數字相同,次數加1 不同則次數減1.次數為0,則儲存下乙個數字並把次數設為1.我們要找 的數字就是最後一次把次數...