排序复习

归并排序:nlogn

核心思想:递归分治,每次先把左右两个区间排好序,然后合并

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=5e6+10;
int n,k,a[N],t[N];
int read(){
	int num=0,f=1;char ch=getchar();
	while(!isdigit(ch)){
		f=-1;ch=getchar();
	}
	while(isdigit(ch)){
		num=num*10+ch-'0';ch=getchar();
	}
	return num*f;
}
void gbsort(int l,int r){
	if(l==r) return;
	int mid=l+r>>1;
	gbsort(l,mid);gbsort(mid+1,r);
	int le=l,ri=mid+1,tmp=l;
	while(tmp<=r){
		while(a[le]<=a[ri]&&le<=mid&&ri<=r) t[tmp++]=a[le++];
		while(a[le]>a[ri]&&ri<=r&&le<=mid) t[tmp++]=a[ri++];
		while(le>mid&&ri<=r) t[tmp++]=a[ri++];
		while(ri>r&&le<=mid) t[tmp++]=a[le++];
	}
	for(int i=l;i<=r;++i) a[i]=t[i];
	return;
}
int main(){
	n=read(),k=read();
	for(int i=1;i<=n;++i) a[i]=read();
	gbsort(1,n);
	printf("%d\n",a[k+1]);
	return 0;
}

快速排序:nlogn

核心思想:在区间内中间找一个数,把小于他的都放在他的左边,大于他的都放在他的右边。这个代码实现难在你不知道你找的那个数,有几个比他小,几个比他大。但其实不用想那么多,设置两个指针从左到右,如果左边的数小于中间的,就指针向右移动,右指针同理。当无法移动的时候,有可能指针在中间的数两侧,那交换之后仍然满足条件。也有可能是一个指针到了当前中间的这个数,这样代表小于中间这个数的数字更多或者大于这个中间数的数字更多,仍然做交换操作即可。直到指针相遇,然后我们再递归分治左右两个区间。

#include<bits/stdc++.h>
using namespace std;
const int N=5e6+10;
int n,k,a[N];
int read(){
	char ch=getchar();
	int num=0,f=1;
	while(!isdigit(ch)){
		f=-1;
		ch=getchar();
	}
	while(isdigit(ch)){
		num=num*10+ch-'0';
		ch=getchar();
	}
	return num*f;
}
void qsort(int l,int r){
	if(l>=r) return;
	int i=l,j=r,mid=a[l+r>>1];
	while(i<=j){
		while(a[i]<mid) i++;
		while(a[j]>mid) j--;
		if(i<=j){
			swap(a[i],a[j]);
			i++,j--;
		}
	}
	qsort(l,j);qsort(i,r);
}
int main(){
	n=read(),k=read();
	for(int i=1;i<=n;++i) a[i]=read();
	qsort(1,n);
	printf("%d\n",a[k+1]);
	return 0;
} 

然后如果是求第k小的数,用快速排序,类似二分查找的方法,只分治左右其中一个区间,我们就可以O(n)的复杂度解决问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值