剑指offer面试题30最小的k个数

来源:互联网 发布:微博登录网络异常 编辑:程序博客网 时间:2024/05/17 09:08
/*这种题目一看就知道可以用partition算法做。。。 和上面一题几乎一样的的再敲一遍代码把  这种方法的弊端是 要改变原来的数组 还有一种O(nlogk) 的算法就是维护一个最大堆 这牙膏不改变原来数组但是堆。现在让我写 我已经写不出来了 就用有限队列就可以还可以用红黑数RBtree stl的set map 都是用红黑树的rbtree就是通过把节点分为红色和黑色两种颜色 然后一定的规则。。保证一定程度的树平衡可以用set multiset*/#include<iostream>#include<cstdio>#include<queue>#include<cstdlib>using namespace std;int RandInRange(int a,int b){    return rand()%(b-a)+a;}void Swap(int & a,int &b){    int tmp=a;    a=b;    b=tmp;}int Partition(int * arr,int len,int start,int end){    int index=RandInRange(start,end);    int small=start-1;    swap(arr[index],arr[end]);    for(index=start;index<end;++index)    {        if(arr[index]<arr[end])        {            small++;            if(small!=index)            {                swap(arr[small],arr[index]);            }        }    }    ++small;    swap(arr[small],arr[index]);    return small;}/*O(n)的算法 但是要改变原来的数组*/void FindKMinNum(int * arr,int len,int k){    int start=0;    int end=len-1;    int index=Partition(arr,len,start,end);    while(index!=k)    {        if(index>k)        {            end=index-1;            index=Partition(arr,len,start,end);        }        else        {            start=index+1;            index=Partition(arr,len,start,end);        }    }    for(int i=0;i<k;++i)    {        printf("%d ",arr[i]);    }    printf("\n");}/*priority_queue就是最大堆。*/void FindKMinNum_2(int * arr,int len,int k){    priority_queue<int> pq;    if(k>len)    k=len;    for(int i=0;i<k;++i)    pq.push(arr[i]);    for(int i=k;i<len;++i)    {        if(arr[i]<pq.top())        {            pq.pop();            pq.push(arr[i]);        }    }    while(!pq.empty())    {        printf("%d ",pq.top());        pq.pop();    }    printf("\n");}int main(){    int arr[]={4,5,1,6,2,7,3,8};    int len=sizeof arr/sizeof *arr;    int k=4;    FindKMinNum(arr,len,k);    FindKMinNum_2(arr,len,k);    return 0;}