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

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

分析:

方法(1):排序(升序),找前k个数据

vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        //在n个数中找最小的前k个数(排序)
        
        vector<int> v;
        if(k<=0 || input.size()<=0 || k>input.size())
            return v;
        
        sort(input.begin(), input.end());//默认是升序
        int i=0;
        while(i<k)
        {
            v.push_back(input[i]);
            i++;
        }
        return v;
    }

方法(2):用n个数据的前建k个元素的大堆,然后用剩下的元素与堆顶元素比较,比堆顶小的元素入堆,直到完,最后堆中保留的就是最小的前k个元素

//向下调整算法(建大堆)
        void Adjustdown(vector<int>& a, int n, int parent)
        {
            int child=parent*2+1;//左孩子
            while(child<n)
            {
                if(child+1<a.size() && a[child+1]>a[child])//保证a[child]是最大孩子
                {
                    child++;
                }
                
                if(a[parent]<a[child])
                {
                    swap(a[parent], a[child]);
                    
                    parent=child;
                    child=parent*2+1;
                }
                else
                {
                    break;
                }
            }
        }
    
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        //在n个数中找最小的前k个数(堆)
        
        vector<int> v;
        if(k<=0 || input.size()<=0 || k>input.size())
            return v;
        
        //先拿前k个数建一个大堆
        
        //从最后一个节点的父亲开始调整
        for(int i=(k-2)/2;i>=0;i--)
        {
            Adjustdown(input,k,i);
        }
        
        //将剩下的数据与堆顶数据比较,小于堆顶元素就入堆(替换堆顶,并且将堆顶向下调整)
        for(int i=k;i<input.size();i++)
        {
            if(input[i]<input[0])
            {
                input[0]=input[i];
                Adjustdown(input,k, 0);
            }
        }
        
        //小堆中数据尾插到返回的vector中
        for(int i=0;i<k;i++)
        {
            v.push_back(input[i]);
        }
     
       return v;
    }

方法(3):使用优先级队列(要显式传greater仿函数,因为这才是升序,默认是降序的),将原来vector的数据依次push到这个优先级队列中,可以使得最后的元素按照升序排序,然后将前k个push到返回的vector中

vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        //在n个数中找最小的前k个数(排序)
        
        vector<int> v;
        if(k<=0 || input.size()<=0 || k>input.size())
            return v;
        
        priority_queue<int, vector<int>, greater<int>> q;//小堆
        
        for(int i=0;i<input.size();i++)//建立优先级队列(升序排序)
        {
            q.push(input[i]);
        }
        
        while(k)
        {
            v.push_back(q.top());
            q.pop();
            k--;
        }
        
        return v;
    }

方法(4):利用快排思想,找到一个基准值,使得它大于左边所有数,小于右边所有数,如果这个基准值的下标是k-1的话就说明找到了,否则反复找,直到知道为止

int partion(vector<int>& v, int begin, int end)
    {
        int key=v[begin];//保存v[begin]到变量key里
        
        while(begin<end)
        {
            while(begin<end && v[end]>=key)
            {
                end--;
            }
            //来到这,说明v[end]<key
            v[begin]=v[end];
            
            while(begin<end && v[begin]<=key)
            {
                begin++;
            }
            //来到这说明v[behin]>key了
            v[end]=v[begin];
        }
        //来到这v[begin]的是<key
        v[begin]=key;
        
        return begin;
    }
    
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        //在n个数中找最小的前k个数(堆)
        
        vector<int> v;
        if(k<=0 || input.size()<=0 || k>input.size())
            return v;
        
        //调用partion函数看返回的pos是不是k-1(最小的前k个数据,下标是0,1...k-1)
        int pos=partion(input, 0, input.size()-1);
        
       while(pos!=k-1)
        {
            if(pos>k-1)//说明在左半面
            {
                pos=partion(input, 0, pos-1);
            }
            else
            {
                pos=partion(input, pos+1, input.size()-1);
            }
        }
        //来到这说明pos==k-1了
        
        vector<int> v1(input.begin(), input.begin()+k);
        return v1;
    }

猜你喜欢

转载自blog.csdn.net/zy20150613/article/details/90077053