一、面试问题描述
给定一个若干个学生的分数数组,数组中的分数是无序的,在该数组中找出其第K个最小的数,例如对于分数数组arr,arr={89,67,69,60,88,83,75,56,96},则其第3个最小的数为67。
二、解题思路
算法跟快排的思路相似,首先在数组中选取第一个数x=arr[0]为划分的基准,将比x小的数,放到x的前面。将比x大的数,放到x的后面。如果此时x的位置刚好为k,则x为第k个最小的数;如果此时x的位置比k小,则第k个最小数一定在x的右边区域,递归地在其右边寻找。如果此时x的位置比k大,则第k个最小数一个在X的左边区域,递归地在其左边寻找。
三、代码实现
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
int Partition (int arr[],int p,int r)
{
int i = p,j =r+1;
int x = arr[p];
//将小于x的元素交换到左边区域
//将大于x的元素交换到右边区域
while(true){
while(arr[++i]<x&&i<r);
while(arr[--j]>x);
if(i>=j) break;
swap(arr[i],arr[j]);
}
//把枢纽放在正确的位置
arr[p] = arr[j];
arr[j] = x;
return j;
}
int findNumberK(int arr[],int k,int left,int right)
{
if(left<right)
{
int q = Partition(arr,left,right);
//如果此时x的位置刚好为k,则arr[i]为第k个最小的数
if(q+1==k)
return arr[q];
else if(q+1<k)
{
//如果此时x的位置比k前,递归地在其右边寻找
findNumberK(arr,k,q+1,right);
}
else
{
//如果此时x的位置比k后,递归地在其左边寻找
findNumberK(arr,k,left,q-1);
}
}
}
int main()
{
int arr[]= {89,67,69,60,88,83,75,56,96};
int result = 0;
result = findNumberK(arr,3,0,8);
cout<<result<<endl;
system("pause");
}