1.问题描述
寻找数组中第K大的数。
2.问题分析
1、如果使用暴力比较,每一个数字和剩余所有数字比一次,时间复杂度为O(n^2);
2、如果先将数组排序,然后再取出第k个数,时间复杂度为O(nlogn);
3、如果使用快速排序的思想,快排每次执行,可以确定一个元素的最终位置,如果经过若干次排序,找到了位置为n-k的元素,那么这个元素就是第k大的数。时间复杂度为O(n)。
算法描述:
Repeat:执行快排,得到基准数的位置为m;
if m = n-k
Then 得到arr[m]即为第k大的数
if m > n-k
Then 第k大的数在0~m-1之间,递归执行快排
else
Then 第k大的数在m+1~n之间,递归执行快排
3.代码
#include "stdlib.h"
#include <iostream>
using namespace std;
int Partition(int *arr, int low, int high)
{
int temp = arr[low];
while(low < high)
{
while(low < high && arr[high] >= temp)
high--;
arr[low] = arr[high];
while(low < high && arr[low] <= temp)
low++;
arr[high] = arr[low];
}
arr[low] = temp;
return low;
}
int KthElement(int *arr, int low, int high, int n, int k)
{
if(arr == NULL || low >= high || k >n)
return -1;
int pos = Partition(arr, low, high);
while(pos != n-k)
{
if(pos > n-k)
{
high = pos - 1;
pos = Partition(arr, low, high);
}
if(pos < n-k)
{
low = pos+1;
pos = Partition(arr, low, high);
}
}
return arr[pos];
}
int main(int argc, char* argv[])
{
int a[] = {9,4,5,23,7,1};
cout << KthElement(a,0,5,6,3) << endl;
system("pause");
return 0;
}
4.总结
本题的关键在于使用快排的思想,使用基准数的最终位置与n-k做比较,递归找出位置为n-k的基准数即为第k大的数。