找第k小的数

该博客介绍了如何使用快速排序的思路设计一个平均时间复杂度为O(n)的算法,来在1到1000个无序整数中找到第k小的数。算法主要通过partition函数对数组进行划分,并递归地在划分后的子数组中查找目标元素。代码示例展示了具体实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

设计一个平均时间为O(n)的算法,在n(1<=n<=1000)个无序的整数中找出第k小的数。

提示:函数int partition(int a[],int left,int right)的功能是根据a[left]~a[right]中的某个元素x(如a[left])对a[left]~a[right]进行划分,划分后的x所在位置的左段全小于等于x,右段全大于等于x,同时利用x所在的位置还可以计算出x是这批数据按升非降序排列的第几个数。因此可以编制int find(int a[],int left,int right,int k)函数,通过调用partition函数获得划分点,判断划分点是否第k小,若不是,递归调用find函数继续在左段或右段查找。

这里利用快速排序的思路,快排就是找个基准元素,一般是左边第一个,然后从右边开始比较,当右边的元素大于等于基准元素时,就继续(right--) 当小于时就跳出这个循环,然后将这个元素填入基准元素所处的位置,然后从左边开始比较,当左边的元素小于等于基准元素时(left++)直到左边的元素大于基准元素,就将左边的这个元素填入之前右边空出来那个位置,循环直到左右的下标相等即left==right   然后就将基准元素填入这个位置 至此第一次快排结束,基准左边都是小于等于他的,基准右边都是大于等于他的

#include <iostream>
using namespace std;

int partition(int a[],int left,int right){
	int w = a[left];
	while(left<right){
		//先从右边开始 当右边大于等于基数就跳过
		while(left<right&&a[right]>=w){	
			right--;
		}
		//当右边小于基数就跳出循环 然后让右边的数来到基数位置
		a[left] = a[right];
		//然后就从左边继续  左边小于等于基数就跳过 
		while(left<right&&a[left]<=w){
			left++;
		}
		//左边大于基数时 此时右边哪个来到基数的位置是空的 让左边的数座落到那个位置
		a[right] = a[left];
		
	}
	//此时左右指针相遇  把基数填入
	a[left] = w;
	return left;
}

int find(int a[],int left,int right,int k){
	int position = partition(a,left,right);
	//如果索要查找的第k个元素(崽数组中下标为k-1)刚好就是这个快排的基准元素排序后的下标就直接输出
	if(k-1 == position){
		cout<<a[k-1]<<endl;
	}
	else if(k-1<position){ //索要查找的第k个小的元素的位置小于position位置 那么就是position位置之前的某个数
	//因为快排之后 position位置之前的元素都小于position位置的元素
		find(a,left,position-1,k);
	}
	else{
		find(a,position+1,right,k);
	}
	return 0;
}

int main(){
	int n,k;
	cin>>n>>k;
	
	int a[1000];
	for(int i = 0;i<n;i++){
		cin>>a[i];
	}
	find(a,0,n-1,k);
	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值