您的位置:首页 > 职场人生

面试100题:5.查找最小的k个元素

2012-11-05 12:34 429 查看
转载并参考July的博客http://topic.csdn.net/u/20101126/10/b4f12a00-6280-492f-b785-cb6835a63dc9.html,万分感谢!

题目:
输入n个整数,输出其中最小的k个。例如输入1,2,3,4,5,6,7,8和4这几个数字,则最小的4个数字为1,2,3和4。
解一:

/*Title: 5.求n个数中最小的k个:解一
Author:  gocode
Date:    2012-10-03*/

#include<iostream>
using namespace std;

class MinK
{
private:
    void shiftDown(int *ret,int pos,int length)
    {
        int t=ret[pos];
        for(int s=2*pos+1;s<=length;s=2*s+1)
        {
            if(s<length&&ret[s]<ret[s+1])
                ++s;
            if(t<ret[s])
            {
                ret[pos]=ret[s];
                pos=s;
            }
            else break;
        }
        ret[pos]=t;
    }

    int *array;
    int size;

public:    
    MinK(int *arr,int si):array(arr),size(si){}
    bool kmin(int k,int*& ret)
    {
        if(k>size)
        {
            ret=NULL;
            return false;
        }
        else
        {
            ret=new int[k--];
            int i;
            for(i=0;i<=k;++i)
                ret[i]=array[i];
            for(int j=(k-1)/2;j>=0;--j)
                shiftDown(ret,j,k);
            for(;i<size;++i)
                if(array[i]<ret[0])
                {
                    ret[0]=array[i];
                    shiftDown(ret,0,k);
                }
                return true;
        }
    }

    void remove(int*& ret)
    {
        delete[] ret;
        ret=NULL;
    }
};

int main()
{
    int array[]={1,2,3,4,5,6,7,8};
    MinK mink(array,sizeof(array)/sizeof(array[0]));
    int *ret;
    int k=4;
    if(mink.kmin(k,ret))
    {
        for(int i=0;i<k;++i)
            cout<<ret[i]<<" ";
        cout<<endl;
        mink.remove(ret);
    }

    system("pause");
    return 0;
}


解二:
思路:利用make_heap选出vector前K个数的最大值,对于后面的元素,与最大值作比较,如果小于最大值,则替换最大值,然后再次make_heap,选出当前k个数中的最大值。此种解法利用STL函数跳过了建堆过程。make_heap是标准算法库里的模板函数,用于将存储在vector/deque中的元素进行堆操作,将[start, end)范围进行堆排序,默认使用less<int>, 即最大元素放在第一个,也即大根堆
/*Title: 5.求n个数中最小的k个:解二-最大堆
Author:  gocode
Date:    2012-10-03*/

#include <iostream>
#include <vector>
#include <algorithm> // 用于使用make_heap()和sort()
using namespace std;

// 利用make_heap()函数创建最大根堆,这样0-K个数中得最大值被保留在数组的第一个位置
// 然后让数组的第一个值和N-K之后的数组值比较,发现小的就替换
// 并重新构建最大根堆,永远保持数组第一个值是堆中最大,直到替换完
void find(vector<int> &a, int k)
{
    if(a.size() < k)
        return;

    // 构建最大根的堆结构
    make_heap(a.begin(), a.begin() + k);
 
    // 将堆中的最大值替换为k之后的小值,然后重新构建堆
    for(vector<int>::size_type i = k; i != a.size(); i++)
    {
        if(a[i] < a[0])
        {
            a[0] = a[i];
            make_heap(a.begin(), a.begin() + k);
        }
    }

    // 从小到大排序
    sort(a.begin(), a.begin() + k);

    // 打印
    for(vector<int>::size_type i = 0; i != k; i++)
        cout<<a[i]<<" ";
}

int main()
{
    vector<int> a;
    for(int j = 8; j > 0; j--)
        a.push_back(j);
 
    find(a, 4);
    system("pause");
    return 0;
}


解三:
每次循环求出数组0-K个数的最大值max,然后和N-K个值比较,把小的值赋给max。
参考:http://xingyunbaijunwei.blog.163.com/blog/static/7653806720122293850244/
/*Title: 5.求n个数中最小的k个:解三-数组
Author:  gocode
Date:    2012-10-03*/

#include<stdlib.h>
#include<stdio.h>

#define K 4  // K个最小值
#define N 10 // 数组容量

// 求当前datas[0]...datas[K]数组里的最大值
// 并与N-K个值newdata做比较
// 如max小于datas[N-K],则交换
void replace(int datas[], int newdata)
{
    int i, pos = -1, max = -(2<<31);
    for(i = 0; i < K; i++)
    {
        if(max < datas[i])
	{
	    max = datas[i];
	    pos = i;
        }
    }
 
    if(newdata < datas[pos])
        datas[pos] = newdata;
}

void main()
{
    int datas[K] = {0};
    int j = 0, input;
 
    // 这里的input.txt位置是相对于*.cpp文件的
    // freopen会把文件里的内容读入到stdin中
    freopen("Debug\\input.txt","r",stdin);
 
    // 这里的scanf会把上面stdin里的内容赋值给input
    // EOF表示流末尾
    while(EOF != scanf("%d", &input)) 
    {
        if(j < K)
            datas[j++] = input;
        else
            replace(datas, input);
    }

    printf("List array:\n");
    for(j = 0; j < K; j++)
        printf("%d ",datas[j]);

    fclose(stdin);
    system("pause"); // 使程序暂停,可以看console的结果
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: