经典算法:超大数组,取出最大N数

来源:互联网 发布:传奇版本火灵db数据 编辑:程序博客网 时间:2024/06/03 17:59

转载于:http://blog.csdn.net/yanzi1225627/article/details/8109035


这里先讲一种类似于快速排序的方法。注意题目要求,不要求完全排序,只要求最快解决问题!这个题是我面试NI公司时,对方问我的。原话是从1亿个数据里,找出前一百个最大的。


首先看源码吧:

void findMaxN(int a[], int start, int end, int N)//从数组a里,找出前N个最大的。如果是a[100],则start = 0, end = 99.注意这个索 引问题{    int mid = (start + end)/2;   int i = start, j = end;while(i<j){    while(i<j && a[i]<=a[mid])     i++;  while(i<j && a[j]>=a[mid])   j--;swap(a[i], a[j]);}/*注意这个while出来之后,i一定是等于j的,且从i 到 end是较大的那一端*/if(end-i+1 == N)return;if(end - i+1 > N)findMaxN(a, i, end, N);else  findMaxN(a, start, i, N - (end -i +1));}


     再来详细说说思路,如果您看懂了快速排序对此一定不会陌生。首先拿a[mid] 做基准值,然后让i, j从两端开始遍历,如果索引小的那一端数据小于基准值a[mid], 就往前遍历,如果 左边的大于了a[mid], while循环会跳出,记住这时的a[i] 是大于a[mid],

       然后类似的思路,从j那一端遍历,当右边的数据a[j ] 小于基准值a[mid],则小while循环会跳出。然后会运行swap()这个函数,将两个值进行交换 。 这样最外面的while循环出来之后,i一定是等于j的,注意这里i 和j不一定等于当前域中的mid。而且从i到end都是较大的,然后看看较大的那一端的数据有多少个,然后进行遍历。

      如果已经等于要找的N个,则跳出函数。如果大于N,则要从i到end为区间内接着找;如果小于N,比如说要找前50个最大的,结果end-i+1才等于20,也就是从i到end有20个较大的数,这就需要从 start(第一次时,可以认为是0)到i 区间内再找50-20 = 30个最大的。

    至于swap的函数,利用引用实现如下:

void swap(int &a, int &b)
{

   int temp = a;

   a = b;

   b= temp;

}


     最后说说,如果这个函数执行完毕了,我怎么访问找到的最大的N个数呢? 很简单,假设数组长度为n, 从a[n-1], a[n-2]。。。顺序取N个数,就是找到的最大的前N个数据了!这个算法的最大情况时间复杂度是o(n的平方),最好情况是o(n), 平坦下来也是o(n).

   等我空我介绍第二种思路,上面代码是即兴写的,源码我一会上传。

http://download.csdn.net/detail/yanzi1225627/4684046


0 0
原创粉丝点击