排序题练习:最小的K个数

本文对比介绍了几种常见的排序算法,如sort函数的O(nlog2n)效率、插入排序的O(n^2)、选择排序、堆排序(O(nlogk))、冒泡排序(O(nk))和快速排序(O(nlogn)),重点推荐了堆排序作为找到最小K个数的高效解决方案。
摘要由CSDN通过智能技术生成

题目描述

最小的K个数

推荐堆排序

利用sort函数-时间复杂度n*log2(n)

class Solution {
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        sort(input.begin(),input.end());
        return vector<int>({input.begin(),input.begin()+k}); 
    }
};

插入排序

直接插入排序-时间复杂度O(n^2)

class Solution {
public:
    void InsertSort(vector<int>&a,int len)
    {
        for(int i=1;i<len;i++)
        {
            if(a[i-1]>a[i])
            {
                int temp=a[i],j;
                for(j=i-1;a[j]>temp;j--)
                    a[j+1]=a[j];
                a[j+1]=temp;
            }
        }
    }
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        int len=input.size();
        InsertSort(input,len-1);
        return vector<int>({input.begin(),input.begin()+k}); 
    }
};

选择排序

简单选择排序-时间复杂度O(nk)

每次选择一个最小的元素,循环k轮,可得到最小的k个数。时间复杂度O(nk)

class Solution {
public:
    void SelectSort(vector<int> &a,int k,int len)
    {//简单选择排序
        int min_i;
        for(int i=0;i<k;i++)
        {
            min_i=i;
            for(int j=i+1;j<len;j++)
                if(a[j]<a[min_i])min_i=j;
            swap(a[min_i],a[i]);
        }
    }
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        int len=input.size();
        SelectSort(input,k,len);
        return vector<int>({input.begin(),input.begin()+k}); 
    }
};

(推荐)堆排序-时间复杂度O(nlogk)

可以借助大根堆来完成。始终保持堆中元素为k个,起初根据input的前k个元素建立初堆,之后依次使input中的值与堆中最大元素比较,即与堆顶元素比较(由于是大根堆,因此堆顶元素为堆中k各元素的最大值)。
用数组a[1…k]来存储堆。若input[i]中元素小于堆顶元素,则将堆顶元素a[1]input[i]置换,之后再调整堆

class Solution {
public:
    void AdjustHeap(int a[],int k,int len)
    {
        a[0]=a[k];
        for(int i=2*k;i<=len;i*=2)
        {
            if(a[i+1]>a[i]&&i<len)i++;
            if(a[i]>a[0])
            {
                a[k]=a[i];
                k=i;
            }
            else break;
        }
        a[k]=a[0];
    }
    void CreateHeap(int a[],int len)
    {
        for(int i=len/2;i>=1;i--)
            AdjustHeap(a, i, len);
    }
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        int *a=new int[k+1];
        int len=input.size();
        for(int i=1;i<=k;i++)
            a[i]=input[i-1];//a中存放k个元素
        CreateHeap(a, k);//建长度为k的初堆
        int temp;
        for(int i=k;i<len;i++)//依次检查input[k....len-1]的元素
        {
            if(input[i]<a[1])
            {
                a[1]=input[i];
                AdjustHeap(a, 1, k);//调整a[1....k]为大根堆
            }
        }
        input.clear();
        for(int i=1;i<=k;i++)
            input.push_back(a[i]);
        return input;
    }
};

交换排序

冒泡排序-时间复杂度O(nk)

冒泡排序是一种基于交换的排序,每次冒泡能从未排序序列中选出一个最小的,因此k趟循环后能够选出最小的k个数。每一轮循环中,比较的次数不超过n-1,故平均时间复杂度为O(nk)

class Solution {
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        //冒泡排序,循环k轮
        int len=input.size();
        for(int i=1;i<=k;i++)
        {
            bool flag=false;
            for(int j=len-1;j>0;j--)
            {
                if(input[j]<input[j-1])
                {
                    swap(input[j],input[j-1]);
                    flag=true;
                }
            }
            if(flag==false)break;
        }
        return vector<int>({input.begin(),input.begin()+k});
    }
};

快速排序-时间复杂度O(nlogn)

注意函数参数里的引用!
由于快排的最好时间复杂度为O(nlogn),且平时使用时快排总是接近最好时间复杂度,因此考虑使用快排

class Solution {
public:
    int Part(vector<int>&a,int low,int high)
    {
        int temp=a[low];
        while(low<high)
        {
            while(low<high&&a[high]>=temp)--high;
            a[low]=a[high];
            while(low<high&&a[low]<=temp)++low;
            a[high]=a[low];
        }
        a[low]=temp;
        return low;
    }
    void QuickSort(vector<int>&a,int low,int high)
    {
        if(low<high)
        {
            int part=Part(a,low,high);
            QuickSort(a, low, part-1);
            QuickSort(a, part+1,high);
        }        
    }
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        //快速排序
        int len=input.size()-1;
        QuickSort(input, 0, len);
        return vector<int>({input.begin(),input.begin()+k}); 
    }
};

归并排序-时间复杂度O(nlogn)

class Solution {
public:
    void Merge(vector<int> &a,int low,int mid,int high)
    {
        int i=low,j=mid+1,k=low;
        int len=a.size();
        int *temp=new int[len];
        for(int r=low;r<=high;r++)
            temp[k++]=a[r];
        for(k=low;i<=mid&&j<=high;k++)
        {
            if(temp[i]<temp[j])a[k]=temp[i++];
            else a[k]=temp[j++];
        }
        while(i<=mid)a[k++]=temp[i++];
        while(j<=high)a[k++]=temp[j++];
    }
    void MergeSort(vector<int> &a,int low,int high)
    {//归并排序
        int mid;//对于low+high的值大的情况,这种写法可以防止溢出
        if(low<high)
        {
            mid=low+(high-low)/2;
            MergeSort(a, low, mid);
            MergeSort(a, mid+1, high);
            Merge(a, low,mid,high);
        }
    }
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        int len=input.size();
        MergeSort(input,0,len-1);
        return vector<int>({input.begin(),input.begin()+k}); 
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值