日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

找出发帖的水王问题

發布時間:2024/1/17 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 找出发帖的水王问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Tango是微軟亞洲研究院的一個試驗項目。研究院的員工和實習生們都很喜歡在Tango上面交流灌水。傳說,Tango有一大“水王”,他不但喜歡發貼,還會回復其他ID發的每個帖子。坊間風聞該“水王”發帖數目超過了帖子總數的一半。如果你有一個當前論壇上所有帖子(包括回帖)的列表,其中帖子作者的ID也在表中,你能快速找出這個傳說中的Tango水王嗎?

分析與解法

首先想到的是一個最直接的方法,我們可以對所有ID進行排序。然后再掃描一遍排好序的ID列表,統計各個ID出現的次數。如果某個ID出現的次數超過總數的一半,那么就輸出這個ID。這個算法的時間復雜度為O(N * log2N + N)。

如果ID列表已經是有序的,還需要掃描一遍整個列表來統計各個ID出現的次數嗎?

如果一個ID出現的次數超過總數N的一半。那么,無論水王的ID是什么,這個有序的ID列表中的第N/2項(從0開始編號)一定會是這個ID(讀者可以試著證明一下)。省去重新掃描一遍列表,可以節省一點算法耗費的時間。如果能夠迅速定位到列表的某一項(比如使用數組來存儲列表),除去排序的時間復雜度,后處理需要的時間為O(1)。

但上面兩種方法都需要先對ID列表進行排序,時間復雜度方面沒有本質的改進。能否避免排序呢?

如果每次刪除兩個不同的ID(不管是否包含“水王”的ID),那么,在剩下的ID列表中,“水王”ID出現的次數仍然超過總數的一半。看到這一點之后,就可以通過不斷重復這個過程,把ID列表中的ID總數降低(轉化為更小的問題),從而得到問題的答案。新的思路,避免了排序這個耗時的步驟,總的時間復雜度只有O(N),且只需要常數的額外內存。偽代碼如下:

代碼清單2-8

Type Find(Type* ID, int N)
{
??? Type candidate;
??? int nTimes, i;
??? for(i = nTimes = 0; i < N; i++)
??? {
??????? if(nTimes == 0)
??????? {
???????????? candidate = ID[i], nTimes = 1;
????????}
??????? else
??????? {
????????????if(candidate == ID[i])
??????????????? nTimes++;
??????????? else
??????????????? nTimes--;

??????? }

??? }
????return candidate;
}

在這個題目中,有一個計算機科學中很普遍的思想,就是如何把一個問題轉化為規模較小的若干個問題。分治、遞推和貪心等都是基于這樣的思路。在轉化過程中,小的問題跟原問題本質上一致。這樣,我們可以通過同樣的方式將小問題轉化為更小的問題。因此,轉化過程是很重要的。像上面這個題目,我們保證了問題的解在小問題中仍然具有與原問題相同的性質:水王的ID在ID列表中的次數超過一半。轉化本身計算的效率越高,轉化之后問題規模縮小得越快,則整體算法的時間復雜度越低。

擴展問題

隨著Tango的發展,管理員發現,“超級水王”沒有了。統計結果表明,有3個發帖很多的ID,他們的發帖數目都超過了帖子總數目N的1/4。你能從發帖ID列表中快速找出他們的ID嗎?

參考上面的解法,思路如下:
如果每次刪除四個不同的ID(不管是否包含發帖數目超過總數1/4的ID),那么,在剩下的ID列表中,原先發帖比例大于1/4的ID所占比例仍然大于1/4。可以通過不斷重復這個過程,把ID列表中的ID總數降低(轉化為更小的問題),從而得到問題的答案。

代碼如下:

void Find(Type* ID, int N,Type candidate[3])
{
??? Type ID_NULL;//定義一個不存在的ID
??? int nTimes[3], i;
??? nTimes[0]=nTimes[1]=nTimes[2]=0;
??? candidate[0]=candidate[1]=candidate[2]=ID_NULL;
??? for(i = 0; i < N; i++)
??? {
??????? if(ID[i]==candidate[0])/*先進行賦值,i=0時給第一個id,i=1時若id1!=ca0;id1就賦值給ca1,以此循環,知道times—為0;進入time=0的語句中,開始新的循環,同時就把原來的id刪掉*/
??????? {
???????????? nTimes[0]++;
??????? }
??????? else if(ID[i]==candidate[1])
??????? {
???????????? nTimes[1]++;
??????? }
??????? else if(ID[i]==candidate[2])
??????? {
???????????? nTimes[2]++;
??????? }
??????? else if(nTimes[0]==0)
??????? {
???????????? nTimes[0]=1;
???????????? candidate[0]=ID[i];
??????? }
??????? else if(nTimes[1]==0)
??????? {
???????????? nTimes[1]=1;
???????????? candidate[1]=ID[i];
??????? }
??????? else if(nTimes[2]==0)
??????? {
???????????? nTimes[2]=1;
???????????? candidate[2]=ID[i];
??????? }
??????? else
??????? {
???????????? nTimes[0]--;
???????????? nTimes[1]--;
???????????? nTimes[2]--;
???????? }
??? }
??? return;
}

總結

以上是生活随笔為你收集整理的找出发帖的水王问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。