zoukankan      html  css  js  c++  java
  • 查找最小的k个元素 【微软面试100题 第五题】

    题目要求:

      输入n个整数,输出其中最小的k个。

      例如:输入1,2,3,4,5,6,7,8这8个数字,则最小的4个数字为1,2,3,4。

    参考资料:剑指offer第30题。

    题目分析:

      解法一:

        用快排的思想,但是最小的k个数不用排序,时间复杂度O(n).

        优点:时间复杂度好,缺点:会修改原整数数组顺序。

      解法二:

        创建一个大小为k的最大堆,遍历一遍数组,同时不断修改最大堆。时间复杂度O(nlogk).

        优点:不会修改原数组,适用于海量数据。缺点:比解法一时间复杂度高。

      其他解法:

        1.快排,取前k个数,时间复杂度O(nlogn).

        2.遍历k次,时间复杂度O(k*n).

        3.位图排序,取前k个数,时间复杂度O(n).会占用额外的空间.

    解法一代码:

    #include <iostream>   
    #include <stdlib.h>    
    using namespace std;   
    
    inline int my_rand(int low, int high)   
    {   
        int size = high - low + 1;   
        return  low + rand() % size;   
    }
    int partition(int a[], int low, int high)   
    {   
        int val = a[low];
    
        while(low<high)
        {
            while( (low<high) && (a[high]>=val) )
                high--;
    
            a[low] = a[high];
            while( (low<high) && (a[low] <= val) )
                low++;
            a[high] = a[low];
        }
        a[low] = val;
        return low;
    }
    void swap(int *a,int i,int j)
    {
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
    bool rand_select(int array[], int left, int right, int k)   
    {   
        //第k 小元素,实际上应该在数组中下标为 k-1   
        if (k-1 > right || k-1 < left)      
            return false ;   
    
        if(left<right)
        {
            //随机从数组中选取枢纽元元素   
            int index = my_rand(left, right);
            swap(array,index,left);
    
            int pos = partition(array , left, right);   
            if(pos == k-1)   
                return true ;   
            else if (pos > k-1)   
                return rand_select(array , left, pos-1, k);   
            else return rand_select(array, pos+1, right, k); 
        }
        else
            return true ; 
    }   
    int main()   
    {   
        int array1[] = {7, 8, 9, 12, 6, 4, 11, 1, 2, 33};      
    
        int numOfArray = sizeof (array1) / sizeof( int);   
        for(int i=0; i<numOfArray; i++)   
            cout << array1[i] << " ";
        cout << endl;
    
        int K = 5;      
        bool flag = rand_select(array1, 0, numOfArray-1, K);     
        
        if(flag)
        {
            cout << "最小的" << K << "个数为:";
            for(int i=0; i<K; i++)   
                cout << array1[i] << " ";
            cout << endl;
        }
        return 0;   
    }  
    View Code

    解法二代码:

    //从头实现一个最大堆需要一定的代码,可以采用c++中的红黑树来实现。
    //其中set和multiset都是基于红黑树实现的,后者可以支持数组中有重复
    #include <iostream>
    #include <set>
    #include <vector>
    
    using namespace std;
    
    typedef multiset<int,greater<int>> intSet;
    typedef multiset<int,greater<int>>::iterator setIterator;
    
    void getLeastNumbers(const vector<int> &data,intSet &leastNumbers,int k);
    
    int main(void)
    {
        int a[8] = {1,2,8,4,5,6,7,3};
        const vector<int> data(a,a+8);//8不是7
    
        intSet leastNumbers;
        int k = 5;
    
        getLeastNumbers(data,leastNumbers,k);
        
        cout << "最小的" << k << "个数为:";
        setIterator iter = leastNumbers.begin();
        for(;iter!=leastNumbers.end();++iter)
            cout << *iter << " ";
        cout << endl;
        return 0;
    }
    void getLeastNumbers(const vector<int> &data,intSet &leastNumbers,int k)
    {
        leastNumbers.clear();
    
        if(k<1 || k>data.size())
            return ;
    
        vector<int>::const_iterator iter = data.begin();
        for(;iter != data.end();++iter)
        {
            if(leastNumbers.size() < k)
                leastNumbers.insert(*iter);
            else
            {
                setIterator iterGreatest = leastNumbers.begin();
                if(*iter < *iterGreatest)
                {
                    leastNumbers.erase(*iterGreatest);
                    leastNumbers.insert(*iter);
                }
            }
        }
    }
    View Code
  • 相关阅读:
    Mysql登录错误:ERROR 1045 (28000): Plugin caching_sha2_password could not be loaded
    Docker配置LNMP环境
    Docker安装mysqli扩展和gd扩展
    Docker常用命令
    Ubuntu常用命令
    单例模式的优缺点和使用场景
    ABP 多租户数据共享
    ABP Core 后台Angular+Ng-Zorro 图片上传
    ERROR Error: If ngModel is used within a form tag, either the name attribute must be set or the form control must be defined as 'standalone' in ngModelOptions.
    AbpCore 执行迁移文件生成数据库报错 Could not find root folder of the web project!
  • 原文地址:https://www.cnblogs.com/tractorman/p/4053558.html
Copyright © 2011-2022 走看看