寻找最小的K个数

来源:互联网 发布:sql是什么的缩写 编辑:程序博客网 时间:2024/06/02 11:51

今天看到一篇文章 http://blog.csdn.net/v_JULY_v/article/details/6370650 ,文章写的很细,大家讨论的也很多,在C语言下采用了堆数据结构,一般我都是用C++,所以对C++还是熟悉一点,STL中就专门有关于堆的算法,make_heap,sort_heap,push_heap,pop_heap,用这几个函数就能解决那篇blog的问题了,这里我就不想再谈关于堆的问题了,看了题目后我自己想了一个方法,用BitSet类解决问题,代码如下:

#include <iostream>
#include <bitset>

using namespace std;
const int SIZE = 1024;
const int ARRAYSIZE = 7;

int main(){
   int Array[] = {9,8,6,4,13,85,250};
   int k = 3;
   int count = 0;

   bitset<SIZE> little;  //with 0 initialized
   for(int i = 0;i < ARRAYSIZE;++i)
      little.set(Array[i]);
   for(int i = 0;i < SIZE;++i){
      if(little.test(i)){
         cout<<i<<" ";
     count++;
     if(count == k)
     break;
      }
   }
}

相比原代码,程序就显得很短小了,这里主要用到了bitset类,用一个比特来表示某个数字的存在,如果5存在,那么little.set(5)将设置little的第5位为1,这样遍历整个数组,就设置好了对应的位,然后再遍历little,找出被设置了1的前K个位,输出相应的数字就可以了,算法的复杂度为O(n),当然这是有前提的,也就是说所给的数组种不能有特别大的数字,也就是说如果所给数组为{3,6,8,233333333,5666666,222222222},如果需要最小的4个数,那么这个算法将会遍历little的前5666666位,算法的时间复杂度将大大上升,而且空间复杂度也会到O(m),m位数组中最大的数。

所以说这个算法可以应用,但是是在特定的场景下的,当给的数的大小波动不大,数组中最大的数和数组的大小相差不多时,这时就可以用到这个算法了,若其他情况则就只能用堆数据结构来解决问题了。

对于{222222,3333333,555555,777777,8888888}这样的数组,我们可以同时把所有元素减去最小的元素,这样就得到了{0,111111,333333,555555,666666},这样所需要的比特数就是最大的数减去最小的数再加1了,这样看来这种算法和计数排序还是很像的,计数排序假设输入的元素都是0到k之间的整数,需要一个额外的数组,数组的大小也是最大的数字减去最小的数字再加一,计数排序的好处是可以允许有重复的数字,而且此排序还是稳定的,使用bitset算法内存上只有计数排序的1/8,但是这里不能允许有重复的数字,因为一个比特只能表示0和1,无法表示出个数的信息。

所以这里如果输入数组波动不大,除了计数排序O(n)的复杂度外,使用bitset也可以达到线性复杂度。

0 0
原创粉丝点击