文章目录
题目描述
推荐堆排序
利用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});
}
};