zoukankan      html  css  js  c++  java
  • 寻找最小的k个数

    1. 能想到的最直接的办法,就是对数组进行排序,最好的排序算法的时间复杂性为O(n*logn),这一个方法请参照各种排序算法。

    2. 另外申请一个k空间数组,依次更改里面的最大值,每做一次最多要扫描一下这个K大小的空间(如果比上一次的最大值大的话,就不用扫描了,所以这里说是“最多”),整体时间复杂度为O((n-k)*k),实现代码如下:

    #include <iostream>
    #include <cstdlib>
    #include <ctime>
    using namespace std;
    
    int initData(int test[],int len);
    int printArray(int test[],int len);
    int maxOfArray(int test[],int k);
    int selectElement(int test[],int len,int k);
    
    int main()
    {
        const int arraySize=100;
        const int k=20;
        int test[arraySize];
        initData(test,arraySize);
        printArray(test,arraySize);
        selectElement(test,arraySize,k);
        printArray(test,k);
        return 0;
    }
    int selectElement(int test[],int len,int k)
    {
        int maxIndex=maxOfArray(test,k);
        for(int i=k;i<len;i++)
        {
            int tmp=test[maxIndex];
            if(tmp>test[i])
            {
                test[maxIndex]=test[i];
                maxIndex=maxOfArray(test,k);
            }
        }
        return 0;
    }
    int maxOfArray(int test[],int k)
    {
        int index=0;
        int tmp=test[0];
        for(int i=1;i<k;i++)
        {
            if(test[i]>tmp)
            {
                index=i;
                tmp=test[i];
            }
        }
        return index;
    }
    int initData(int test[],int len)
    {
        srand(time(NULL));
        for(int i=0;i<len;i++)
        {
            test[i]=rand()%20;
        }
        return 0;
    
    }
    int printArray(int test[],int len)
    {
        for(int i=0;i<len;i++)
        {
            cout<<test[i]<<"	";
        }
        cout<<endl;
        return 0;
    }

    3.第三种方式是建立一个k大小的极大堆,每一次将数据与堆头的元素比较,如果比它小,则替换之,然后更新堆的结构,除去构建堆的时间,时间复杂度为:O((n-k)*logk),代码如下:

    #include <iostream>
    #include <cstdlib>
    #include <ctime>
    using namespace std;
    
    
    int initData(int test[],int len);
    int printArray(int test[],int len);
    int maxHeap(int test[],int i,int k);//i为下标
    int buildHeap(int test[],int arraySize,int k);
    int selectElement(int test[],int arraySize,int k);
    int main()
    {
        const int arraySize=20;
        const int k=5;
        int test[arraySize];
        initData(test,arraySize);
        printArray(test,arraySize);
        buildHeap(test,arraySize,k);
        printArray(test,arraySize);
        selectElement(test,arraySize,k);
        printArray(test,arraySize);
        return 0;
    }
    int selectElement(int test[],int arraySize,int k)
    {
        for(int i=k;i<arraySize;i++)
        {
            if(test[i]<test[0])
            {
                test[0]=test[i];
                maxHeap(test,0,k);
            }
        }
        return 0;
    }
    int buildHeap(int test[],int arraySize,int k)
    {
        for(int i=arraySize/2-1;i>=0;i--)
        {
            maxHeap(test,i,k);
        }
        return 0;
    }
    int maxHeap(int test[],int i,int k)//i为下标
    {
        int least=i;
        int left=(i+1)*2-1;
        int right=(i+1)*2;
        if(left<k&&test[left]>test[least])
            least=left;
        if(right<k&&test[right]>test[least])
            least=right;
        if(least!=i)
        {
            test[i]=test[i]+test[least];
            test[least]=test[i]-test[least];
            test[i]=test[i]-test[least];
            maxHeap(test,least,k);
        }
        return 0;
    }
    int initData(int test[],int len)
    {
        srand(time(NULL));
        for(int i=0;i<len;i++)
        {
            test[i]=rand()%20;
        }
        return 0;
    
    }
    int printArray(int test[],int len)
    {
        for(int i=0;i<len;i++)
        {
            cout<<test[i]<<"	";
        }
        cout<<endl;
        return 0;
    }

     对堆不了解的这里插入一个3D动画http://www.benfrederickson.com/2013/10/10/heap-visualization.html

    4. 第四种方法是借鉴快速排序的partition过程,partition做完后,假设返回的下标是k,那么我们确定k之前的元素都比k下标的元素要小,依次不断递归下去,时间复杂度是O(n),实现代码如下:

    #include <iostream>
    #include <cstdlib>
    #include <ctime>
    using namespace std;
    int partition(int test[],int p,int r);
    int selectElements(int test[],int p,int r,int k);//前k个最小元素;
    int initData(int test[],int len);
    int printArray(int test[],int len);
    
    
    int main()
    {
        const int arraySize=10;
        const int k=5;
        int test[arraySize];
        initData(test,arraySize);
    
        printArray(test,arraySize);
        selectElements(test,0,arraySize-1,k);
        printArray(test,arraySize);
        return 0;
    }
    int selectElements(int test[],int p,int r,int k)//前k个最小元素
    {
        if(p<=r)
        {
            int partIndex=partition(test,p,r);
            int len=partIndex-p+1;
            if(len==k)
                return 0;
            else if(len<k)
            {
                selectElements(test,partIndex+1,r,k-len);
            }
            else
            {
                selectElements(test,p,partIndex-1,k);
            }
        }
        return 0;
    }
    int partition(int test[],int p,int r)
    {
            int flagValue=test[r];
            int k=p-1;
            for(int i=p;i<r;i++)
            {
                if(test[i]<flagValue)
                {
                    k++;
                    /*
                    test[i]=test[k]+test[i];test[k]与test[i]是同一块区域的话,这样会把数据清0
                    test[k]=test[i]-test[k];
                    test[i]=test[i]-test[k];
                    */
                    int tmp=test[k];
                    test[k]=test[i];
                    test[i]=tmp;
                }
            }
            k++;
            test[r]=test[k];
            test[k]=flagValue;
            return k;
    
    }
    int initData(int test[],int len)
    {
        srand(time(NULL));
        for(int i=0;i<len;i++)
        {
            test[i]=rand()%20;
        }
        return 0;
    
    }
    int printArray(int test[],int len)
    {
        for(int i=0;i<len;i++)
        {
            cout<<test[i]<<"	";
        }
        cout<<endl;
        return 0;
    }
  • 相关阅读:
    C#关于日期 月 天数 和一年有多少周及根据某年某周获取时间段的计算
    配置tomcat
    C# 动态编译及反射执行
    数据库日志自增量太大导致超时
    validateRequest验证引发错误“检测到有潜在危险的 Request.Form 值”
    入手了DELL Ultrabook,还不错哦!
    Spring.NET学习笔记1——控制反转(基础篇)
    Win7 64位下Kindle4、闪迪Cruzer BladeU盘等无法安装驱动问题的解决方法
    转:CentOS 5.5下LVM分区在线扩容
    [转]关于64位Sublime Text 2破解注册码的方法
  • 原文地址:https://www.cnblogs.com/wzyj/p/3600380.html
Copyright © 2011-2022 走看看