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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

程序员面试题精选100题(05)-查找最小的k个元素[算法]

發(fā)布時(shí)間:2025/3/21 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 程序员面试题精选100题(05)-查找最小的k个元素[算法] 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

題目:輸入n個(gè)整數(shù),輸出其中最小的k個(gè)。

例如輸入1,2,3,4,5,6,7和8這8個(gè)數(shù)字,則最小的4個(gè)數(shù)字為1,2,3和4。

分析:這道題最簡(jiǎn)單的思路莫過于把輸入的n個(gè)整數(shù)排序,這樣排在最前面的k個(gè)數(shù)就是最小的k個(gè)數(shù)。只是這種思路的時(shí)間復(fù)雜度為O(nlogn)。我們?cè)囍鴮ふ腋斓慕鉀Q思路。

我們可以先創(chuàng)建一個(gè)大小為k的數(shù)據(jù)容器來存儲(chǔ)最小的k個(gè)數(shù)字。接下來我們每次從輸入的n個(gè)整數(shù)中讀入一個(gè)數(shù)。如果容器中已有的數(shù)字少于k個(gè),則直接把這次讀入的整數(shù)放入容器之中;如果容器中已有k個(gè)數(shù)字了,也就是容器已滿,此時(shí)我們不能再插入新的數(shù)字而只能替換已有的數(shù)字。我們找出這已有的k個(gè)數(shù)中最大值,然和拿這次待插入的整數(shù)和這個(gè)最大值進(jìn)行比較。如果待插入的值比當(dāng)前已有的最大值小,則用這個(gè)數(shù)替換替換當(dāng)前已有的最大值;如果帶插入的值比當(dāng)前已有的最大值還要大,那么這個(gè)數(shù)不可能是最小的k個(gè)整數(shù)之一,因?yàn)槲覀內(nèi)萜鲀?nèi)已經(jīng)有k個(gè)數(shù)字比它小了,于是我們可以拋棄這個(gè)整數(shù)。

因此當(dāng)容器滿了之后,我們要做三件事情:一是在k個(gè)整數(shù)中找到最大數(shù),二是有可能在這個(gè)容器中刪除最大數(shù),三是可能要插入一個(gè)新的數(shù)字,并保證k個(gè)整數(shù)依然是排序的。如果我們用一個(gè)二叉樹來實(shí)現(xiàn)這個(gè)數(shù)據(jù)容器,那么我們能在O(logk)時(shí)間內(nèi)實(shí)現(xiàn)這三步操作。因此對(duì)于n個(gè)輸入數(shù)字而言,總的時(shí)間效率就是O(nlogk)。

我們可以選擇用不同的二叉樹來實(shí)現(xiàn)這個(gè)數(shù)據(jù)容器。由于我們每次都需要找到k個(gè)整數(shù)中的最大數(shù)字,我們很容易想到用最大堆。在最大堆中,根結(jié)點(diǎn)的值總是大于它的子樹中任意結(jié)點(diǎn)的值。于是我們每次可以在O(1)得到已有的k個(gè)數(shù)字中的最大值,但需要O(logk)時(shí)間完成刪除以及插入操作。

我們自己從頭實(shí)現(xiàn)一個(gè)最大堆需要一定的代碼。我們還可以采用紅黑樹來實(shí)現(xiàn)我們的容器。紅黑樹通過把結(jié)點(diǎn)分為紅、黑兩種顏色并根據(jù)一些規(guī)則確保樹是平衡的,從而保證在紅黑樹中查找、刪除和插入操作都只需要O(logk)。在STL中set和multiset都是基于紅黑樹實(shí)現(xiàn)的。如果面試官不反對(duì)我們用STL中的數(shù)據(jù)容器,我們就直接拿過來用吧。下面是基于STL中的multiset的參考代碼:

typedef multiset<int, greater<int> > IntHeap;/// // find k least numbers in a vector /// void FindKLeastNumbers (const vector<int>& data, // a vector of dataIntHeap& leastNumbers, // k least numbers, outputunsigned int k ) {leastNumbers.clear();if(k == 0 || data.size() < k)return;vector<int>::const_iterator iter = data.begin();for(; iter != data.end(); ++ iter){// if less than k numbers was inserted into leastNumbersif((leastNumbers.size()) < k)leastNumbers.insert(*iter);// leastNumbers contains k numbers and it's full nowelse{// first number in leastNumbers is the greatest oneIntHeap::iterator iterFirst = leastNumbers.begin();// if is less than the previous greatest number if(*iter < *(leastNumbers.begin())){// replace the previous greatest numberleastNumbers.erase(iterFirst);leastNumbers.insert(*iter);}}} }



本文已經(jīng)收錄到《劍指Offer——名企面試官精講典型編程題》一書中,有改動(dòng),書中的分析講解更加詳細(xì),并且還介紹了一種O(n)的算法。歡迎關(guān)注。在我的英文版博客(

http://codercareer.blogspot.com/2011/09/no-05-least-k-numbers.html )中也討論了這個(gè)問題,感興趣的讀者可以去看看英文的博客。
?????
本題已被 九度Online Judge系統(tǒng)收錄,歡迎讀者移步到 http://ac.jobdu.com/hhtproblems.php在線測(cè)試自己的代碼。

博主何海濤對(duì)本博客文章享有版權(quán)。網(wǎng)絡(luò)轉(zhuǎn)載請(qǐng)注明出處http://zhedahht.blog.163.com/。整理出版物請(qǐng)和作者聯(lián)系。對(duì)解題思路有任何建議,歡迎在評(píng)論中告知,或者加我微博http://weibo.com/zhedahht或者http://t.163.com/zhedahht與我討論。謝謝。

《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的程序员面试题精选100题(05)-查找最小的k个元素[算法]的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

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