选择第n大的数(分治法和排列实现)

个人心得:在买的书上看到的一个经典分治题,题目意思就是给定一个数组,求第k小的数。

第一反应就是排序,然后返回第k-1位置的数就可以了,这样算法的复杂度是nlongn,在快速排序的基础下还是挺不错的。

不过为了学习分治法还是换种思路,这也是建立在快速排序的方法,因为快排是以第一个作为标准,比他小的数在左边,大的数在右边。

所以此时就有nleft表示左边的个数

1:如果nleft=k-1,那么此时flag必然是第k小的数

2:如果大于,那么就在左边找就好了,问题规模变小了

3:如果小于,去右边,不过此时选择k-nelft-1(解释,本代码自动跳跃flag这个数所以还要减去1)

注意问题的转移和基准的确定。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<iomanip>
 6 #include<algorithm>
 7 using namespace std;
 8 #define maxi 105
 9 int a[maxi];
10 int b[maxi];
11 int n,k;
12 void geta(){
13     for(int i=0;i<n;i++)
14         b[i]=a[i];
15 }
16 int sorta(){
17       sort(b,b+n);
18       return b[k-1];
19 }
20 int quickcheck(int left,int right,int ki)
21 {
22     if(left>=right) return a[left];
23     int i=left;
24     int j=right+1;
25     int flag=a[left];
26     while(true){
27         do
28         {
29             i++;
30         }while(a[i]<flag);
31         do
32         {
33             j--;
34         }while(a[j]>flag);
35         if(i>=j) break;
36         swap(a[i],a[j]);
37     }
38     int nleft=j-left;
39     if(nleft==ki-1) return flag;
40     a[left]=a[j];
41     a[j]=flag;
42     if(nleft<ki-1)
43         return quickcheck(j+1,right,ki-nleft-1);
44     else
45         return quickcheck(left,j-1,ki);
46 }
47 
48 int main()
49 {
50    cin>>n>>k;
51    for(int i=0;i<n;i++) cin>>a[i];
52    geta();
53    cout<<sorta()<<endl<<quickcheck(0,n-1,k)<<endl;
54    return 0;
55 }

 

转载于:https://www.cnblogs.com/blvt/p/7822598.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值