• (剑指Offer)面试题30:最小的k个数


    题目:

    输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

    思路:

    1、排序

    把输入的n个整数排序,然后取前k个数;

    时间复杂度:O(nlogn)

    2、Partition

    通过partition找到第k大的数,它的左边就是前k小的数;

    时间复杂度:O(n)

    3、最大堆

    构建k个整数的最大堆数据结构,然后将剩余n-k个整数依次与堆顶比较,大则抛弃,小则删除堆顶并插入,最后的最大堆就是最小的k个整数;

    堆是基于二叉树来实现的,因此插入和删除操作都在O(logk)时间内完成。在代码中可以通过STL中的容器来实现,如set,multiset,priority_queue等,都是基于红黑树实现的,所以是排序的。

    时间复杂度:O(nlogk)

    代码:

    1、Partition方法

    #include <iostream>
    
    using namespace std;
    
    int Partition(int* numbers,int start,int end){
        int key=numbers[start];
        int i=start;
        int j=end;
        while(i<j){
            while(i<j && numbers[j]>=key)
                --j;
            if(i<j) numbers[i++]=numbers[j];
    
            while(i<j && numbers[i]<=key)
                ++i;
            if(i<j) numbers[j--]=numbers[i];
        }
        numbers[i]=key;
        return i;
    }
    
    void GetLeastNumbers(int* input,int n,int* output,int k){
        if(input==NULL || output==NULL || k>n || n<=0 || k<=0)
            return;
        int start=0;
        int end=n-1;
        int index=Partition(input,start,end);
        while(index!=k-1){
            if(index>k-1){
                end=index-1;
                index=Partition(input,start,end);
            }
            else{
                start=index+1;
                index=Partition(input,start,end);
            }
        }
    
        for(int i=0;i<k;i++)
            output[i]=input[i];
    }
    
    int main()
    {
        int A[]={4,5,1,6,2,7,3,8};
        int len=sizeof(A)/sizeof(A[0]);
        int k=4;
        GetLeastNumbers(A,len,A,k);
    
        for(int i=0;i<k;i++)
            cout<<A[i]<<" ";
        cout<<endl;
        return 0;
    }
    

    2、最大堆/大顶堆

    #include <iostream>
    #include <set>
    #include <vector>
    
    using namespace std;
    
    typedef multiset<int,greater<int> > inSet;
    typedef multiset<int,greater<int> >::iterator setIterator;
    
    void GetLeastNumbers_1(const vector<int> &data,inSet &leastNumbers,unsigned int k){
        leastNumbers.clear();
    
        if(k<1 || data.size()<k)
            return;
    
        vector<int>::const_iterator it=data.begin();
        for(;it!=data.end();it++){
            if(leastNumbers.size()<k)
                leastNumbers.insert(*it);
            else{
                setIterator iterGreatest=leastNumbers.begin();
                if(*it<*iterGreatest){
                    leastNumbers.erase(iterGreatest);
                    leastNumbers.insert(*it);
                }
            }
        }
    }
    
    int main()
    {
        int A[]={4,5,1,6,2,7,3,8};
        int len=sizeof(A)/sizeof(A[0]);
        int k=4;
        vector<int> data(A,A+len);
       
        inSet leastNumbers;
        GetLeastNumbers_1(data,leastNumbers,k);
    
        for(setIterator it=leastNumbers.begin();it!=leastNumbers.end();it++)
            cout<<*it<<" ";
        cout<<endl;
    
        return 0;
    }
    

    在线测试OJ:

    http://www.nowcoder.com/books/coding-interviews/6a296eb82cf844ca8539b57c23e6e9bf?rp=2

    AC代码:

    1、Partition方法:

    class Solution {
    public:
        int Partition(vector<int> &data,int start,int end){
            int key=data[start];
            int i=start;
            int j=end;
            while(i<j){
                while(i<j && data[j]>=key)
                    j--;
                if(i<j)
                	data[i++]=data[j];
                while(i<j && data[i]<=key)
                    i++;
                if(i<j)
                	data[j--]=data[i];
            }
            data[i]=key;
            return i;
        }
        
        vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
            vector<int> output;
            if(k<1 || input.size()<k)
                return output;
            int start=0;
            int end=input.size()-1;
            int index=Partition(input,start,end);
            while(index!=k-1){
                if(index>k-1){
                    end=index-1;
                    index=Partition(input,start,end);
                }
                else{
                    start=index+1;
                    index=Partition(input,start,end);
                }
            }
            
            for(int i=0;i<k;i++)
                output.push_back(input[i]);
            
            return output;
        }
    };
    

    2、大顶堆:multiset

    class Solution {
    public:
        typedef multiset<int,greater<int> > inSet;
        typedef multiset<int,greater<int> >::iterator inSetIterator;
        vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
            vector<int> output;
            if(k<1 || input.size()<k)
                return output;
            
            inSet LeastNumbers;
            for(vector<int>::iterator it=input.begin();it!=input.end();it++){
                if(LeastNumbers.size()<k)
                    LeastNumbers.insert(*it);
                else{
                    inSetIterator greatest=LeastNumbers.begin();
                    if(*it<*greatest){
                        LeastNumbers.erase(*greatest);
                        LeastNumbers.insert(*it);
                    }
                }
            }
            
            for(inSetIterator it=LeastNumbers.begin();it!=LeastNumbers.end();it++)
                output.push_back(*it);
            
            return output;
        }
    };

    3、大顶堆:priority_queue

    class Solution {
    public:
        typedef priority_queue<int,vector<int>,less<int> > PQ;
        vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
            vector<int> output;
            if(k<1 || input.size()<k)
                return output;
    
            PQ LeastNumbers;
            for(vector<int>::iterator it=input.begin();it!=input.end();it++){
                if(LeastNumbers.size()<k)
                    LeastNumbers.push(*it);
                else{
                    int greatest=LeastNumbers.top();
                    if(*it<greatest){
                        LeastNumbers.pop();
                        LeastNumbers.push(*it);
                    }
                }
            }
            while(!LeastNumbers.empty()){
                output.push_back(LeastNumbers.top());
                LeastNumbers.pop();
            }
    
            return output;
        }
    };
  • 相关阅读:
    20080619 SQL SERVER 输入 NULL 的快捷键
    20090406 Adobe的“此产品的许可已停止工作”错误的解决办法
    20080908 Office Powerpoint 2007 不能输入中文的解决办法
    20080831 ClearGertrude Blog Skin 's cnblogs_code class
    20080603 Facebook 平台正式开放
    20080519 安装 Microsoft SQL Server 2000 时提示 创建挂起的文件操作
    test
    Linux—fork函数学习笔记
    SOA的设计理念
    Why BCP connects to SQL Server instance which start with account of Network Service fail?
  • 原文地址:https://www.cnblogs.com/AndyJee/p/4672862.html
Copyright © 2020-2023  润新知