題目:輸入n個整數,輸出其中最小的k個。
例如輸入1,2,3,4,5,6,7和8這8個數字,則最小的4個數字為1,2,3和4。
分析:這道題最簡單的思路莫過於把輸入的n個整數排序,這樣排在最前面的k個數就是最小的k個數。只是這種思路的時間複雜度為o(nlogn)。我們試著尋找更快的解決思路。
我們可以開闢乙個長度為k的陣列。每次從輸入的n個整數中讀入乙個數。如果陣列中已經插入的元素少於k個,則將讀入的整數直接放到陣列中。否則長度為k的陣列已經滿了,不能再往陣列裡插入元素,只能替換了。如果讀入的這個整數比陣列中已有k個整數的最大值要小,則用讀入的這個整數替換這個最大值;如果讀入的整數比陣列中已有k個整數的最大值還要大,則讀入的這個整數不可能是最小的k個整數之一,拋棄這個整數。這種思路相當於只要排序k個整數,因此時間複雜可以降到o(n+nlogk)。通常情況下
k要遠小於
n,所以這種辦法要優於前面的思路。
從給面試官留下更好印象的角度出發,我們可以進一步把**寫得更漂亮一些。從上面的分析,當長度為k的陣列已經滿了之後,如果需要替換,每次替換的都是陣列中的最大值。在常用的資料結構中,能夠在o(1)時間裡得到最大值的資料結構為最大堆。因此我們可以用堆(heap)來代替陣列。
這個地方大家可以好好想想,為什麼要用到大頂堆,為什麼不是小頂堆?
由於我們這裡是要找最小的k個數,在堆中元素還小於k的時候,我們每讀入乙個資料,都是進入插入到堆中的,當堆中已經有了k個元素後,我們讀到k+1個元素,此時就分兩種情況:
由於我們要找k個最小的數,所以淘汰的應該是這k+1個數中最大的乙個,既然是最大的,自然是用大頂堆了
如果當前讀入的第k+1個數比堆中的最大值還要大,則直接將其它淘汰,如果小,則要淘汰堆中的最大值
這裡自然想到,如果是求最大的k個數,我們就要用到小頂堆了。
另外,自己重頭開始寫乙個最大堆需要一定量的**。我們現在不需要重新去發明車輪,因為前人早就發明出來了。同樣,stl中的set和multiset為我們做了很好的堆的實現,我們可以拿過來用。可以給面試官留下熟悉stl的好印象!
下面貼出測試**:
這裡注意大頂堆的形式:
typedef multiset < int, greater < int > > iniheap;
注意幾點:
小頂堆是multiset < int, less < int > >
它的插入操作是不帶迭代器的,即insert(x)
從begin() 到 end(),堆中資料按大到小排列。
程式設計師面試題精選
問題描述 輸入乙個字串,列印出該字串中字元的所有排列。例如輸入字串abc,則輸出由字元a b c所能排列出來的所有字串abc acb bac bca cab和cba。問題分析 這是一道很好的考查對遞迴理解的程式設計題。寫遞迴程式關鍵有兩點,處理好進入與返回的關係,進入時改變了什麼,返回時應當恢復。字...
程式設計師面試題精選(5) 查詢最小的k個元素
題目 輸入n個整數,輸出其中最小的k個。例如輸入1,2,3,4,5,6,7和8這8個數字,則最小的4個數字為1,2,3和4。分析 這道題最簡單的思路莫過於把輸入的n個整數排序,這樣排在最前面的k個數就是最小的k個數。只是這種思路的時間複雜度為o nlogn 我們試著尋找更快的解決思路。我們可以開闢乙...
程式設計師面試題精選100題
今天開始各種刷面試題,沉下心來集中時間,全身心投入 題目 輸入一棵二元查詢樹,將該二元查詢樹轉換成乙個排序的雙向鍊錶。要求不能建立任何新的結點,只調整指標的指向。比如將二元查詢樹 10 6 14 4 8 12 16 轉換成雙向鍊錶 4 6 8 10 12 14 16。相關概念 二元查詢樹 它首先要是...