第k大 or 第k小 or 中位数

c++里面有模板,这里不赘述。主要是c语言实现.
主要思想是递归+快排

1.用一个数组,进行原址选择,缺点是只能进行一次。
将一个数组以某一个元素a作为基准(这里选取最后一个),将这个数组划分,使得左边的元素都比a大,右边的都比a小。当然如果是求第K小,只需对k进行转换即可。

#include<stdio.h>
void swap(int *a,int *b)
{
	int t=*a;
	*a=*b;
	*b=t;
}
*num数组名,k第几大,n元素个数,p,r分别是数组下标
int k_max(int *num,int k,int n,int p,int r)
{
	int num1,num2;//统计左边、右边元素各有多少个
	num1=num2=0;
	int i=p-1;
	int key=num[r];//基准
	//下面是快排思想
	if(p<r)
	{
		for(int j=p;j<r;j++)
		{
			if(num[j]<key)
			{
				i++;
				num1++;
				swap(&num[i],&num[j]);
			}
		}
		swap(&num[r],&num[i+1]);
	}
	else return num[r];//终止条件
	num2=n-num1;
	if(num1>=k)
	{
	//第k大的元素在左边元素里
		return k_max(num,k,num1,p,p+num1-1);
	}
	else
	{
	//在右边元素里
		return k_max(num,k-num1,num2,p+num1,r);
	}
}
int main(void)
{
	int n;
	scanf("%d",&n);
	int num[100001]={0};
	for(int i=1;i<=n;i++)
	{
		scanf("%d",num+i);
	}
		int i,j,k;//分别为数组下标,第几大
		scanf("%d%d%d",&i,&j,&k);
		printf("%d\n",k_max(num,k,j-i+1,i,j));
}

2.再开两个数组,优点是可以多次进行。

#include<stdio.h>
void swap(int *a,int *b)
{
	int t=*a;
	*a=*b;
	*b=t;
}
int sav1[100001];
int sav2[100001];
int k_max(int *num,int k,int n,int p,int r)
{
	int i,l;
	i=l=0;
	int key=num[r];
	if(p<r)
	{
		for(int j=p;j<=r;j++)
		{
			if(num[j]<key)
			{
				sav2[++i]=num[j];
			}
			else if(num[j]>key)
			{
		
				sav1[++l]=num[j];
			}
		}
	}
	else return num[r];
	if(l>=k)
	{
		return k_max(sav1,k,l,1,l);
	}
	else if(l<k-1)
	{
		return k_max(sav2,k-l-1,i,1,i);
	}
	else return key;
}
int main(void)
{
	int n,m;
	scanf("%d%d",&n,&m);
	int num[100001]={0};
	for(int i=1;i<=n;i++)
	{
		scanf("%d",num+i);
	}
	while(m--)//指令条数
	{
		int i,j,k;
		scanf("%d%d%d",&i,&j,&k);
		printf("%d\n",k_max(num,k,j-i+1,i,j));当所求为第k小时,只需k=j-i-k+2;
	}
}

注意二者的区别,在1中我们把基准元素也进行排序,而2中不对基准元素进行排序,所以2中的特别判断key是不是所求。
如果我们仍然采用1中递归结束的标志,那么会出现死循环。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值