ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2021-07-19 19:02:06  阅读:140  来源: 互联网

标签:int 复杂度 练习 个数 len vector low input 排序


文章目录

题目描述

最小的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}); 
    }
};

标签:int,复杂度,练习,个数,len,vector,low,input,排序
来源: https://blog.csdn.net/qq_44807176/article/details/118891723

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有