题目大致意思就是给一个无序数组,让你来找到第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;
}