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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

[转]第(前)k大数问题

發(fā)布時(shí)間:2024/8/22 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [转]第(前)k大数问题 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
以前做過(guò)這種題,可是又給忘了。腦子還是活動(dòng)不開(kāi)……
在網(wǎng)上搜了搜,發(fā)現(xiàn)這種問(wèn)題有很多種解法,并且衍生出來(lái)很多新的問(wèn)題。貼出來(lái)給大家看看。
轉(zhuǎn)自http://summerbell.javaeye.com/blog/510394
---------------------------------------------------------------------------------------------------------

所謂“第(前)k大數(shù)問(wèn)題”指的是在長(zhǎng)度為n(n>=k)的亂序數(shù)組中S找出從大到小順序的第(前)k個(gè)數(shù)的問(wèn)題。

?

解法1我們可以對(duì)這個(gè)亂序數(shù)組按照從大到小先行排序,然后取出前k大,總的時(shí)間復(fù)雜度為O(n*logn+k)

?

解法2利用選擇排序或交互排序,K次選擇后即可得到第k大的數(shù)。總的時(shí)間復(fù)雜度為O(n*k)

?

解法3利用快速排序的思想,從數(shù)組S中隨機(jī)找出一個(gè)元素X,把數(shù)組分為兩部分Sa和Sb。Sa中的元素大于等于X,Sb中元素小于X。這時(shí)有兩種情況:

1.Sa中元素的個(gè)數(shù)小于k,則Sb中的第k-|Sa|個(gè)元素即為第k大數(shù);

2.Sa中元素的個(gè)數(shù)大于等于k,則返回Sa中的第k大數(shù)。時(shí)間復(fù)雜度近似為O(n)

///

回憶一下快速排序,快排中的每一步,都是將待排數(shù)據(jù)分做兩組,其中一組的數(shù)據(jù)的任何一個(gè)數(shù)都比另一組中的任何一個(gè)大,然后再對(duì)兩組分別做類(lèi)似的操作,然后繼續(xù)下去……

在本問(wèn)題中,假設(shè)N個(gè)數(shù)存儲(chǔ)在數(shù)組S中,我們從數(shù)組S中隨機(jī)找出一個(gè)元素X,把數(shù)組分為兩部分Sa和Sb。Sa中的元素大于等于X,Sb中元素小于X。

這時(shí),有兩種可能性:

1.???Sa中元素的個(gè)數(shù)小于K,Sa中所有的數(shù)和Sb中最大的K-|Sa|個(gè)元素(|Sa|指Sa中元素的個(gè)數(shù))就是數(shù)組S中最大的K個(gè)數(shù)。

2.???Sa中元素的個(gè)數(shù)大于或等于K,則需要返回Sa中最大的K個(gè)元素。

這樣遞歸下去,不斷把問(wèn)題分解成更小的問(wèn)題,平均時(shí)間復(fù)雜度O(N * log2K

?

解法4:二分[Smin,Smax]查找結(jié)果X,統(tǒng)計(jì)X在數(shù)組中出現(xiàn),且整個(gè)數(shù)組中比X大的數(shù)目為k-1的數(shù)即為第k大數(shù)。時(shí)間復(fù)雜度平均情況為O(n*logn)

?

解法5O(4*n)的方法對(duì)原數(shù)組建最大堆,然后pop出k即可。時(shí)間復(fù)雜度為O(4*n+k*logn)

?

解法6:維護(hù)一個(gè)k大小的最小堆,對(duì)于數(shù)組中的每一個(gè)元素判斷與堆頂?shù)拇笮?#xff0c;若堆頂較大,則不管,否則,彈出堆頂,將當(dāng)前值插入到堆中。時(shí)間復(fù)雜度O(n*logk)

?

解法7利用hash保存數(shù)組中元素Si出現(xiàn)的次數(shù),利用計(jì)數(shù)排序的思想,線性從大到小掃描過(guò)程中,前面有k-1個(gè)數(shù)則為第k大數(shù),平均情況下時(shí)間復(fù)雜度O(n)

//

上面類(lèi)快速排序的方法平均時(shí)間復(fù)雜度是線性的。能否有確定的線性算法呢?是否可以通過(guò)改進(jìn)計(jì)數(shù)排序、基數(shù)排序等來(lái)得到一個(gè)更高效的算法呢?答案是肯定的。但算法的適用范圍會(huì)受到一定的限制。

如果所有N個(gè)數(shù)都是正整數(shù),且它們的取值范圍不太大,可以考慮申請(qǐng)空間,記錄每個(gè)整數(shù)出現(xiàn)的次數(shù),然后再?gòu)拇蟮叫∪∽畲蟮腒個(gè)。比如,所有整數(shù)都在(0, MAXN)區(qū)間中的話,利用一個(gè)數(shù)組count[MAXN]來(lái)記錄每個(gè)整數(shù)出現(xiàn)的個(gè)數(shù)(count[i]表示整數(shù)i在所有整數(shù)中出現(xiàn)的個(gè)數(shù))。我們只需要掃描一遍就可以得到count數(shù)組。然后,尋找第K大的元素。

?

?

附注:

1.STL中可以用nth_element求得類(lèi)似的第n大的數(shù)(由謂詞決定),使用的是解法3中的思想,還可以用partial_sort對(duì)區(qū)間進(jìn)行部分排序,得到類(lèi)似前k大的數(shù)(由謂詞決定),它采用的是解法5的思想。

2.求中位數(shù)實(shí)際上是第k大數(shù)的特例。

?

《編程之美》2.5節(jié)課后習(xí)題:

1.如果需要找出N個(gè)數(shù)中最大的K個(gè)不同的浮點(diǎn)數(shù)呢?比如,含有10個(gè)浮點(diǎn)數(shù)的數(shù)組(1.5,1.5,2.5,3.5,3.5,5,0,-1.5,3.5)中最大的3個(gè)不同的浮點(diǎn)數(shù)是(5,3.5,2.5)。

解答:上面的解法均適用,需要注意的是浮點(diǎn)數(shù)比較時(shí)和整數(shù)不同,另外求hashkey的方法也會(huì)略有不同。

2.如果是找第k到第m(0<k<=m<=n)大的數(shù)呢?

解答:如果把問(wèn)題看做m-k+1個(gè)第k大問(wèn)題,則前面解法均適用。但是對(duì)于類(lèi)似前k大這樣的問(wèn)題,最好使用解法5或者解法7,總體復(fù)雜度較低。

3.在搜索引擎中,網(wǎng)絡(luò)上的每個(gè)網(wǎng)頁(yè)都有“權(quán)威性”權(quán)重,如pagerank。如果我們需要尋找權(quán)重最大的K個(gè)網(wǎng)頁(yè),而網(wǎng)頁(yè)的權(quán)重會(huì)不斷地更新,那么算法要如何變動(dòng)以達(dá)到快速更新(incremental update)并及時(shí)返回權(quán)重最大的K個(gè)網(wǎng)頁(yè)?

提示:堆排序?當(dāng)每一個(gè)網(wǎng)頁(yè)權(quán)重更新的時(shí)候,更新堆。還有更好的方法嗎?

解答:要達(dá)到快速的更新,我們可以解法5,使用映射二分堆,可以使更新的操作達(dá)到O(logn)

4.在實(shí)際應(yīng)用中,還有一個(gè)“精確度”的問(wèn)題。我們可能并不需要返回嚴(yán)格意義上的最大的K個(gè)元素,在邊界位置允許出現(xiàn)一些誤差。當(dāng)用戶(hù)輸入一個(gè)query的時(shí)候,對(duì)于每一個(gè)文檔d來(lái)說(shuō),它跟這個(gè)query之間都有一個(gè)相關(guān)性衡量權(quán)重f(query,d)。搜索引擎需要返回給用戶(hù)的就是相關(guān)性權(quán)重最大的K個(gè)網(wǎng)頁(yè)。如果每頁(yè)10個(gè)網(wǎng)頁(yè),用戶(hù)不會(huì)關(guān)心第1000頁(yè)開(kāi)外搜索結(jié)果的“精確度”,稍有誤差是可以接受的。比如我們可以返回相關(guān)性第10001大的網(wǎng)頁(yè),而不是第9999大的。在這種情況下,算法該如何改進(jìn)才能更快更有效率呢?網(wǎng)頁(yè)的數(shù)目可能大到一臺(tái)機(jī)器無(wú)法容納得下,這時(shí)怎么辦呢?

提示:歸并排序?如果每臺(tái)機(jī)器都返回最相關(guān)的K個(gè)文檔,那么所有機(jī)器上最相關(guān)K個(gè)文檔的并集肯定包含全集中最相關(guān)的K個(gè)文檔。由于邊界情況并不需要非常精確,如果每臺(tái)機(jī)器返回最好的K’個(gè)文檔,那么K’應(yīng)該如何取值,以達(dá)到我們返回最相關(guān)的90%*K個(gè)文檔是完全精確的,或者最終返回的最相關(guān)的K個(gè)文檔精確度超過(guò)90%(最相關(guān)的K個(gè)文檔中90%以上在全集中相關(guān)性的確排在前K),或者最終返回的最相關(guān)的K個(gè)文檔最差的相關(guān)性排序沒(méi)有超出110%*K。

解答:正如提示中所說(shuō),可以讓每臺(tái)機(jī)器返回最相關(guān)的K’個(gè)文檔,然后利用歸并排序的思想,得到所有文檔中最相關(guān)的K個(gè)。最好的情況是這K個(gè)文檔在所有機(jī)器中平均分布,這時(shí)每臺(tái)機(jī)器只要K’=K/n(n為所有機(jī)器總數(shù));最壞情況,所有最相關(guān)的K個(gè)文檔只出現(xiàn)在其中的某一臺(tái)機(jī)器上,這時(shí)K’需近似等于K了。我覺(jué)得比較好的做法可以在每臺(tái)機(jī)器上維護(hù)一個(gè)堆,然后對(duì)堆頂元素實(shí)行歸并排序。

5.如第4點(diǎn)所說(shuō),對(duì)于每個(gè)文檔d,相對(duì)于不同的關(guān)鍵字q1,q2,…,qm,分別有相關(guān)性權(quán)重f(d,q1),f(d,q2),…,f(d,qm)。如果用戶(hù)輸入關(guān)鍵字qi之后,我們已經(jīng)獲得了最相關(guān)的K個(gè)文檔,而已知關(guān)鍵字qj跟關(guān)鍵字qi相似,文檔跟這兩個(gè)關(guān)鍵字的權(quán)重大小比較靠近,那么關(guān)鍵字qi的最相關(guān)的K個(gè)文檔,對(duì)尋找qj最相關(guān)的K個(gè)文檔有沒(méi)有幫助呢?

解答:肯定是有幫助的。在搜索關(guān)鍵字qj最相關(guān)的K個(gè)文檔時(shí),可以在qj的“近義詞”相關(guān)文檔中搜索部分,然后在全局的所有文檔中在搜索部分。

閱讀全文
類(lèi)別:算法學(xué)習(xí)?查看評(píng)論

轉(zhuǎn)載于:https://www.cnblogs.com/iammatthew/archive/2010/07/22/1803865.html

總結(jié)

以上是生活随笔為你收集整理的[转]第(前)k大数问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。