輸入n個整數,找出其中最小的k個數。例如輸入4、5、1、6、2、7、3、8 這8個數字,則最小的4個數字是1、2、3、4。
分析:這道題最簡單的思路莫過於把輸入的n個整數排序,排序之後位於最前面的k個數就是最小的k個數,這種思路的時間按複雜度是o(nlogn).
2.1 方法一:時間複雜度為o(n)的演算法,只有當我們可以修改輸入的陣列時可用
思路:從解決面試題39:陣列中出現次數超過一半的數字得到啟發,我們同樣可以基於partition函式解決這個問題,如果基於陣列的第k個數字來調整,則使得比第k個數字小的所有數字都位於陣列的左邊,比第k個數字大的所有數字都位於陣列的右邊,這樣調整之後,位於陣列中左邊的k個數字就是最小的k個數字(這k個數字不一定是排序的),下面是基於這種思路的參考**:
class solution
}swap(input[i+1], input[end]);
return i+1;
}vectorgetleastnumbers_solution(vectorinput, int k)
else
}for(int i=0;i2.2 方法二:時間複雜度為o(nlogk)的演算法,特別適合處理海量資料
我們可以先建立乙個大小為k的資料容器來儲存最小的k個數字,接下來每次從輸入的n個整數中讀入乙個數,如果容器中已有的數字少於k個,則直接把讀入的資料放入容器中,如果容器中已有了k個數字了,也就是容器已滿,此時不能再插入新的數字而只能替換已有的數字,找出這已有的k個數中的最大值,然後拿這次待插入的整數和最大值進行比較,如果待插入的值比當前已有的最大值小,則用這個數替換當前已有的最大值;如果待插入的值比當前已有的最大值還大,那麼這個數不可能是最小的k整數之一,於是我們可以拋棄這個整數。
因此,當容器滿了以後,我們要做三件事:1)在k個整數中找到最大數;2)有可能在這個容器中刪除最大數;3)有可能要插入乙個新數字;如果用乙個二叉樹來實現這個資料容器,那麼我們能在o(logk)時間內實現這三步操作。因此,對於n個輸入數字而言,總的時間效率就是o(nlogk)。
class solution }}
return vector(leastnums.begin(), leastnums.end());
}};
兩種解法的特點比較
基於partition函式的解法
基於堆或者紅黑樹的解法
時間複雜度
o(n)
o(nlogk)
是否需要修改輸入陣列是否
是否適用於海量資料否是
面試題40 最小k個數
題目 輸入n個整數,找出其中最小的k個數 思路 1 如果輸入的陣列可以改變,則基於第k個數來調整,是第k個數左邊的數都小於第k個數,右邊的數都大於第k個數 時間複雜度o n 思路1 void printkminnumberbymethod1 int arr,int length,int k int ...
面試題40 最小的K個數
題目描述 輸入n個整數,找出其中最小的k個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4,方法一 不修改原陣列,時間複雜度o nlgk class solution if result k 1 input i result k 1 input i return...
面試題40 最小的k個數!
題目 輸入n個整數,找出其中最小的k個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4,方法一 堆排序 class solution public vectorgetleastnumbers solution vectorinput,int k return r...