您的位置:首页 > 其它

二分查找之k小数

2015-04-12 23:01 211 查看


题目链接:http://hihocoder.com/problemset/problem/1133

题意:找出序列中第k大的数。

分析:
直接sort排序的算法是O(nlogn),会超时。
(1)通过多次二分查找得到答案的话,实际上的复杂度是O(n)。
(2)利用C++里stl的函数做。

第一种实现,利用快排的思想去做。
//题目:二分查找之k小数
//时间:2015-4-12  21:39
//作者:Miki
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
#include<string>
#include<queue>
#include<utility>

using namespace std;
const int MAX=1000000+10;
typedef long long LL;
int a[MAX];
int n,k;

int AdjustArray(int s[], int l, int r) //返回调整后基准数的位置
{
int i = l, j = r;
int x = s[l]; //s[l]即s[i]就是第一个坑
while (i < j)
{
// 从右向左找小于x的数来填s[i]
while(i < j && s[j] >= x)
j--;
if(i < j)
{
s[i] = s[j]; //将s[j]填到s[i]中,s[j]就形成了一个新的坑
i++;
}

// 从左向右找大于或等于x的数来填s[j]
while(i < j && s[i] < x)
i++;
if(i < j)
{
s[j] = s[i]; //将s[i]填到s[j]中,s[i]就形成了一个新的坑
j--;
}
}
//退出时,i等于j。将x填到这个坑中。
s[i] = x;

return i;
}

int  quick_sort1(int s[], int l, int r)
{
while (l<=r)
{
int i = AdjustArray(s, l, r);//先成挖坑填数法调整s[]
if(i == k)
return s[i];
else if(i > k)
r = i-1;
else
l = i+1;
}
return -1;
}
int main()
{
while(scanf("%d %d",&n,&k)!=EOF)
{
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
printf("%d\n",quick_sort1(a,1,n));
}
return 0;
}


第二种是C++STL的函数(神奇的C++)。
nth_element(first,nth,end);
nth_element(first,nth,end,comp);

comp是排序函数。
从first到end中查找第nth个元素。
求第n小的元素,并把它放在第n位置上。默认从小到大找第n小的元素。

注:查找第k大应该写成
    nth_element(num+1, num+n-k, num+n+1);

    printf("%d\n", num[n-k]);

#include<cstdio>
#include<algorithm>
using namespace std;
int n, k;
int num[1000010];

int main()
{
scanf("%d%d", &n, &k);
for(int i = 1; i <= n; i++)
scanf("%d", &num[i]);
if(k<=0||k>n)
{
printf("-1\n");
return 0;
}
nth_element(num+1, num+k, num+n+1);
printf("%d\n", num[k]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  二分