寻找最小的k个数

来源:互联网 发布:免流网站平台源码 编辑:程序博客网 时间:2024/06/02 08:38

从n个书中找出最小的k个数。

解法有如下几种:

(1)全部排序之后找前k个,时间为O(n*n)

(2)部分排序。维护一个大小为k的数组a[k],遍历n个数的过程中更新数组a。时间为O(k*n)

(3)维护一个容量为k 的大顶堆,遍历过程中更新堆。时间为O(nlogk)。

(4)下面着重介绍一种平均时间复杂度为O(n)的算法,线性选择算法。该算法的思想类似于快速排序。

         选取数组A中一个元素作为主元(pivot)v,用快速排序的过程将A(除v)分成两个集合A1和A2。

  • 如果k<=|A1|,那么第k个最小元素在A1内,此时返回quickSelect(A1, k)
  • 如果k=1+|A1|,那么主元就是最小的第k个元素,返回
  • 否则,这第k个最小元素在A2中,即A2中的第k-|A1|-1个最小元素,此时返回quickSelect(A2, k-|A1|-1)
    class QuickSelectMinK {public:void quickSelect(int arr[], int k, int left, int right) {if(left < right) {int pivot = arr[left];int i = left, j = right - 1;for(;;) {while(arr[++i] > pivot){}while(arr[--j] < pivot){}if(i < j) {swap(arr[i], arr[j]);}else{break;}}//重置主元??swap(arr[i], arr[right-1]);if( k <= i ) {quickSelect(arr, k, left, i - 1);}else if( k > i + 1 ) {quickSelect(arr, k, i + 1, right); }}else {//如果left > right, 利用插入排序调整一下InsertSort(arr + left, right - left + 1);}}}

    此快速选择算法类似于快速排序的划分方法。利用主元把数组划分为A1和A2两个部分,A1<= pivot <=A2 。如果要找的k个元素小于A1 的元素个数,则返回A1中较小的k个元素;否则返回A1中所有元素和A2中较小的k-|A1|个元素,平均情况下能做到O(n)的时间复杂度。

0 0
原创粉丝点击