題目:陣列中有乙個數字出現的次數超過了陣列長度的一半,找出這個數字。
乙個陣列中有很多數,現在我們要找出其中那個出現次數超過總數一半的數字,怎麼找呢?大凡當我們碰到某乙個雜亂無序的東西時,我們人的內心本質期望是希望把它梳理成有序的。所以,我們得分兩種情況來討論,無序和有序。
如果無序,那麼我們是不是可以先把陣列中所有這些數字先進行排序(至於排序方法可選取最常用的快速排序)。排完序後,直接遍歷,在遍歷整個陣列的同時統計每個數字的出現次數,然後把那個出現次數超過一半的數字直接輸出,題目便解答完成了。總的時間複雜度為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 ...