分治1寻找第k个数

题目大致意思就是给一个无序数组,让你来找到第k小的数
输入nm,代表数组元素大小和查找的第k个元素
第二行输入n个数
输出第k大的数在原数组的位置。

使用快排找数,快排不懂得可以去看这个博客(快排链接
大致意思就是将元素分组,定义一个flag 这个flag可以是数组中的任意一个元素(必须在数组中)
左边的都比flag小,右边的都比他大,如果要找第k小的元素的话就看flag的位置是大于k还是小于k,大于k就说明在flag右边,小于k就在flag左边,递归遍历左右的元素
比如原数组是

取flag=25 _______________ 25 9 90 57 3
那么第一次排序后的元素为 3 9 25 57 90
此时左边都比flag 25大,右边都比他小就看flag所在位置与k的关系了,大于就递归右边,小于就递归左边
当k == flag所在位置的时候,就说明找到了就是该位置,就可以返回元素了。
然后再根据原数组找到所在原数组的位置。

#include<iostream>

using namespace std;
int n;
int m_find(int m, int *a, int head, int bottom);
int main(void)
{
	//输入n m 
	int   m;
	cin >> n >> m;
	int a[n+1] ,b[n+1];
	for (int i = 1; i<=n; i++)
	{
		cin >> a[i];
		b[i]=a[i];
	}
	//直接写成函数
	int num = m_find(m, a, 1, n  );
	//找到原数组所在位置。
	for(int i=1;i<=n;i++)
	{
		if(b[i]==num)
		{
			cout<<i;
			break;
		}	
	}
//	cout << num;
	return 0;


}
int m_find(int m, int *a, int he , int bo )//先用非递归写 
{
	int bottom =bo;//保存初始位置与结束位置方便递归
	int head =he;
	
	int find = 0;//改了几次代码,这个find其实没多大用处
	int flag = a[head];//把flag设置成头位置
	int num;   //这就是该数字,第k小的数字
	//int head =0,bottom =n-1;

	int p = head;//指向空位 
	while (!find)
	{
		while (a[bottom] > flag&&head<bottom)
		{
			bottom--;
		}
		//此时 a[bottom]< flag;
 		if(a[bottom]<flag)
 		{
 			a[p] = a[bottom];
			p = bottom;//此时的bottom移到了前面,所以该位置就空出来了但是值没有变
			//head++;
			bottom--; //移动到前一个位置,避免后面判断的时候干扰因为此时的位置上的数字并没有改变
 		}

		 


		//此时bottom 的位置空出来了

 		//a[head] = a[bottom];
//同理移动head
		while (a[head] <= flag&&head<bottom)
		{
			head++;
		}
		if(a[head]>flag)
		{
			a[p] = a[head];
			//此时head的位置空出来了
			p = head;
			//bottom--;
			head++;
		}

		
	if(head >=bottom) 
	{
		break;
	}
	
		 
	}
	a[p] =flag;
 
	 
	if (p>m)//在左边对左边递归 
	{
		 head =he;
		num =m_find(m, a, head, p-1 );
	}
	else if (p<m) //对右边递归
	{
		bottom = bo;
		num=m_find(m, a, p+1 , bottom);
	}
	if (p == m)
	{
		return a[p] ;
	}
	return num;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值