出現次數超過一半的數字

2021-07-06 06:02:29 字數 2048 閱讀 1708

題目:陣列中有乙個數字出現的次數超過了陣列長度的一半,找出這個數字。

乙個陣列中有很多數,現在我們要找出其中那個出現次數超過總數一半的數字,怎麼找呢?大凡當我們碰到某乙個雜亂無序的東西時,我們人的內心本質期望是希望把它梳理成有序的。所以,我們得分兩種情況來討論,無序和有序。

如果無序,那麼我們是不是可以先把陣列中所有這些數字先進行排序(至於排序方法可選取最常用的快速排序)。排完序後,直接遍歷,在遍歷整個陣列的同時統計每個數字的出現次數,然後把那個出現次數超過一半的數字直接輸出,題目便解答完成了。總的時間複雜度為o(nlogn + n)。

但如果是有序的陣列呢,或者經過排序把無序的陣列變成有序後的陣列呢?是否在排完序o(nlogn)後,還需要再遍歷一次整個陣列?

我們知道,既然是陣列的話,那麼我們可以根據陣列索引支援直接定向到某乙個數。我們發現,乙個數字在陣列中的出現次數超過了一半,那麼在已排好序的陣列索引的n/2處(從零開始編號),就一定是這個數字。自此,我們只需要對整個陣列排完序之後,然後直接輸出陣列中的第n/2處的數字即可,這個數字即是整個陣列中出現次數超過一半的數字,總的時間複雜度由於少了最後一次整個陣列的遍歷,縮小到o(n*logn)。

然時間複雜度並無本質性的改變,我們需要找到一種更為有效的思路或方法。

既要縮小總的時間複雜度,那麼可以用查詢時間複雜度為o(1)的hash表,即以空間換時間。雜湊表的鍵值(key)為陣列中的數字,值(value)為該數字對應的次數。然後直接遍歷整個hash表,找出每乙個數字在對應的位置處出現的次數,輸出那個出現次數超過一半的數字即可。

hash表需要o(n)的空間開銷,且要設計hash函式,還有沒有更好的辦法呢?我們可以試著這麼考慮,如果每次刪除兩個不同的數(不管是不是我們要查詢的那個出現次數超過一半的數字),那麼,在剩下的數中,我們要查詢的數(出現次數超過一半)出現的次數仍然超過總數的一半。通過不斷重複這個過程,不斷排除掉其它的數,最終找到那個出現次數超過一半的數字。這個方法,免去了排序,也避免了空間o(n)的開銷,總得說來,時間複雜度只有o(n),空間複雜度為o(1),貌似不失為最佳方法。

舉個簡單的例子,如陣列a[5] = ;

很顯然,若我們要找出陣列a中出現次數超過一半的數字,這個數字便是1,若根據上述思路4所述的方法來查詢,我們應該怎麼做呢?通過一次性遍歷整個陣列,然後每次刪除不相同的兩個數字,過程如下簡單表示:

0 1 2 1 1 =>2 1 1=>1
最終1即為所找。

但是陣列如果是,還能運用上述思路麼?很明顯不能,咱們得另尋良策。

更進一步,考慮到這個問題本身的特殊性,我們可以在遍歷陣列的時候儲存兩個值:乙個candidate,用來儲存陣列中遍歷到的某個數字;乙個ntimes,表示當前數字的出現次數,其中,ntimes初始化為1。當我們遍歷到陣列中下乙個數字的時候:

舉個例子,假定陣列為,按照上述思路執行的步驟如下:

思路清楚了,完整的**如下:

//a代表陣列,length代表陣列長度int findonenumber(int* a, int length)

else

}    return candidate;

}

即針對陣列,套用上述程式可得:

i=0,candidate=0,ntimes=1;

i=1,a[1] != candidate,ntimes--,=0;

i=2,candidate=2,ntimes=1;

i=3,a[3] != candidate,ntimes--,=0;

i=4,candidate=1,ntimes=1;

如果是0,1,2,1,1,1的話,那麼i=5,a[5] == candidate,ntimes++,=2;......

加強版水王:找出出現次數剛好是一半的數字

因為,很明顯,如果是剛好出現一半的話,如此例: 0,1,2,1 :

遍歷到0時,candidate為0,times為1

遍歷到1時,與candidate不同,times減為0

遍歷到2時,times為0,則candidate更新為2,times加1

遍歷到1時,與candidate不同,則times減為0;我們需要返回所儲存candidate(數字2)的下乙個數字,即數字1。

演算法 出現次數超過一半的數字

題目 陣列中有乙個數字出現的次數超過了陣列長度的一半,找出這個數字。考慮到這個問題本身的特殊性,我們可以在遍歷陣列的時候儲存兩個值 乙個candidate,用來儲存陣列中遍歷到的某個數字 乙個ntimes,表示當前數字的出現次數,其中,ntimes初始化為1。當我們遍歷到陣列中下乙個數字的時候 舉個...

陣列中出現次數超過一半的數字

何海濤 劍指offer 名企面試官精講典型程式設計題 九度oj 題目描述 陣列中有乙個數字出現的次數超過陣列長度的一半,請找出這個數字。例如輸入乙個長度為9的陣列。由於數字2在陣列中出現了5次,超過陣列長度的一半,因此輸出2。輸入 每個測試案例包括2行 第一行輸入乙個整數n 1 n 100000 表...

陣列中出現次數超過一半的數字

陣列中出現次數超過一半的數字 陣列中有乙個數字出現的次數超過陣列長度的一半,請找出這個數字。例如輸入乙個長度為9的陣列。由於數字2在陣列中出現了5次,超過陣列長度的一半,因此輸出2。如果不存在則輸出0。class solution count 0 for auto i numbers if i k ...