題目是這樣描述的:「水王」發帖的數目超過了所有帖子的一半,有各個帖子的作者id,求這個水王的id
程式設計之美給出了兩種巧妙的解法
解法一:id排序,那麼id列表中的n/2項即為要找的id(還要排序,時間複雜度為o(nlogn))
解法二:通過查詢,每次從列表中除去兩個不一樣的id,最後就可以得出這個id,時間複雜度o(n)。寫法上也有技巧,不必非要找到乙個不一樣的在繼續下去,如果下乙個一樣,那麼用乙個變數記錄這個次數,把次數+1,遇見不一樣的-1。例如1,1,2,3,4 初始value =1,count =1,第二個1,value = 1,count =2,下乙個2,value=1,count=1,下乙個3,value=3,count=0,下乙個4,value=4,count=1...一直到最後,看下value的值,就是所要找的id。
解法三:這個問題也可以用hash統計,在找出那個id,時間複雜度為o(n),但是空間複雜度比解法二大些,最壞可能為o(n)而解法二為o(1)。
以上兩種方法有思路很特別,但是各有優缺點,下面是我的總結下我的理解~
對與解法二,這個演算法有個缺點,不能確切知道這個id出現多少次,只能知道這個id出現的次數大於n/2。(如果想知道,最後還要遍歷次,在海量資料的時候,多遍歷一次的代價是要考慮的)
對為題擴張下~
對於解法一,如果已知有兩個發帖量在1/3以上的id,可以在排序後,在n/3,2n/3的地方取乙個數,在統計下這兩個數出現的次數,既可以判斷,時間複雜度o(nlogn)+o(n)還是o(nlogn)
對於解法二,同樣上述問題,那麼value和count可以用乙個二維陣列來記錄,同樣時間複雜度為o(n)
在對問題擴充套件下,對海量資料的時候~
解法一就變成了「海量資料找出中位數的問題了」,而且不用全部的排序(不是海量資料的時候也可以按找中位數的方法)~這樣,利用數的特性,每個整數都是用32位的二進位制數表示的,按照最高幾位的順序分塊,(分完後塊是有大小順序的)統計每塊數的個數,就可以確定這個中位數在哪個塊裡面了,在對那個塊這樣運算,最終會找到這個中位數。
對於解法二,也可以遞推下,前提條件式必須是已知有m個發帖量在1/(m+1)個以上的id~如果要儲存的數目多的話,可以用hash-map代替陣列
對於解法三,這樣的情況如果m個數還是沒發讀入記憶體的話,要先對id求hash,在hash分組,在hash-map統計即可,如果可以讀入記憶體則一次hash-map統計即可,在在hash-map中找出符合條件的值。與解法二相比,只是有部分空間複雜度上的降低。
對於解法二的思想「減小問題規模,保持問題原有的性質」,對於原題目,性質就是水王的id 在小問題中仍然是超過總發帖量的一半。所以問題的關鍵就是解答,問題關鍵性質是什麼,怎麼減小問題的規模。對於問題的性質,那麼就是具體問題具體分析了,而縮小規模,或者說是劃分子問題,這個思想動態規劃法,分治法都有用到,很大部分是由問題的性質決定的。
尋找發帖「水王」
分析與解法 首先想到的是乙個最直接的方法,我們可以對所有id進行排序。然後再掃瞄一遍排好序的id列表,統計各個id出現的次數。如果某個id出現的次數超過總數的一半,那麼就輸出這個id。這個演算法的時間複雜度為o n log2 n n 如果id列表已經是有序的,還需要掃瞄一遍整個列表來統計各個id出現...
尋找發帖水王
首先想到的是乙個最直接的方法,我們可以對所有id進行排序。然後再掃瞄一遍排好序的id列表,統計各個id出現的次數。如果某個id出現的次數超過總數的一半,那麼就輸出這個id。這個演算法的時間複雜度為o n log2 n n 如果id列表已經是有序的,還需要掃瞄一遍整個列表來統計各個id出現的次數嗎?如...
尋找發帖「水王」
題目 解法1 對所有id排序,因為該id出現的次數超過總數的一半,對有序的序列,第n 2項即為所求id。解法2 每次刪除兩個不同的id,那麼剩下的id列表中,水王 的id次數仍然超過總數的一半。可以通過不斷重複這個過程,把id列表中的id總數降低,從而得到答案。總的時間複雜度只有o n 且只需要常熟...