n問題描述:
給定乙個論壇所有帖子的列表,其中帖子作者的id也在列表中,水王的發帖數目超過了所有帖子的半,請設計演算法,找出水王!
問題分析:
該問題很直接,簡化一下,就是找乙個陣列中,出現次數最多的數,其中,這個出現次數最多的數的出現次數佔整個陣列大小》50%。
最直觀的方法是對陣列進行排序,然後遍歷,即可找出出現次數最多的數。總的時間複雜度為nlogn+n。
那麼能不能不進行排序而用乙個比較的方法找到這個出現次數最多的數?
注意乙個性質——出現的次數大於整個數大小的組一半。仔細想想這個性質,如果每次刪除兩個不同的id,一樣可以保證這個原來出現次數最多的數在刪除兩個不同的數後,依然滿足關係,依次類推,不斷縮小陣列的大小,最後就可以找到這個出現次數最多的數。
這種思想很巧妙,但是不難想象。更精髓的地方在於如何將這個思想用**實現。
設想一下,從陣列的第乙個數開始,如果第二個數是不同的,那麼我們之前把指標移到第三個數,表示前面兩個數已經被刪除了;但是如果第二個數和第乙個數相同,那麼該怎麼辦?書中的偽碼是這樣做的,找第三個和第四個數,如果第三和第四都不同於第乙個(第二個數,第乙個數等於第二個數),則都刪除,相當於刪除了兩隊。
程式的巧妙之處在於用乙個變數記錄乙個數的出現次數,第一次出現num=1,如果下乙個數是一樣的,則num++,否則則num--,當num = 0,說明了如果這個數出現了n,那麼當n=0時,一定有n個數與之相同,這全部刪除,相當於刪除了n對!
偽**:
type find(type *id,int n)
typecandidate;
intnum,i;
for(i = num = 0;i < n; i++)
if(num == 0)
candidate = id[i];
num++;
else
if(candidate == id[i])
num++;
else
num--;
returncandidate;
書中的**
if(num == 0)
candidate = id[i];
我改為:
if(num == 0)
candidate = id[i];
num++;
不然永遠不能進入1級else
我用自己的程式驗證了這一點,結果如下:
重新開始戰鬥04 程式設計之美 尋找ID問題
問題描述 乙個很大的列表 有10億多個數 這個列表中全是都是id號,正常狀態下每個id都會再列表中出現兩次 都是亂序 1.當有乙個id號丟失時,如何找到這個id號 2.當有兩個id號丟失時,如何找到這兩個id號。解法一 最直觀 申請乙個陣列,這個陣列和id列表一樣大,然後遍歷id列表,每遍歷乙個id...
重新開始戰鬥03 程式設計之美 買書問題
問題描述 由於 哈利波特 系列相當暢銷,店長決定通過 活動來回饋讀者。上櫃的 哈利波特 瓶裝本系列中,一共有5卷。假設每一捲單獨銷售均需8歐元。如果讀者一次購買不同的兩卷,就可以扣除5 的費用,三卷更多。具體的折扣如下 本數 折扣 2 5 3 10 4 20 5 25 每本書只能享受一種折扣。例如買...
重新開始戰鬥05 程式設計之美 光影切割
問題描述 假設有乙個矩形區域,有若干條直線切割該區域,並且沒有一條直線與y軸平行,且不存在三條 以及3條以上 切割線相交於一點的情況。請問該矩形平面被分割成多少塊。分析 假設一塊矩形區域已經被切割成很多塊,那麼此時再增加一條切割線,新的切割線與其他切割線相交,且有m個交點。那麼新的切割線被分割成m ...