问题: 查找出一给定数组中第k大的数。例如[3,2,7,1,8,9,6,5,4],第1大的数是9,第2大的数是8……
思考:
1. 直接从大到小排序,排好序后,第k大的数就是arr[k-1]。
2. 只需找到第k大的数,不必把所有的数排好序。我们借助快速排序中partition过程,一般情况下,在把所有数都排好序前,就可以找到第k大的数。我们依据的逻辑是,经过一次partition后,数组被pivot分成左右两部分:S左、S右。当S左的元素个数|S左|等于k-1时,pivot即是所找的数;当|S左|小于k-1,所找的数位于S右中;当|S左|>k-1,所找的数位于S左中。显然,后两种情况都会使搜索空间缩小。
算法的时间复杂度为:O(N)–详情参考算法导论。
#include<iostream>
using namespace std;
int Partition(int a[], int i, int j)
{
int temp = a[i];
if (i < j)
{
while (i < j)
{
//从后往前扫找比枢轴值小的交换位置
while (i<j&&a[j] >= temp) j--;
if (i < j) a[i] = a[j];
while (i < j&&a[i] < temp) i++;
if (i < j) a[j] = a[i];
}
a[i] = temp;
return i;
}
}
int Search(int a[], int i, int j, int k)
{
int m = Partition(a, i, j);
if (k==m-i+1) return a[m];
else if (k<m-i+1)
{
return Search(a, i, m-1,k );
}
//后半段
else
{
return Search(a, m+1, j, k-(m-i+1));
}
}
int main()
{
int a[7] = { 1,2,3,4,6,7,8 };
int k = 3;
cout << Search(a,2, 6, k);
}