分区算法解决问题

任务描述

本关任务:

 独立完成中值问题。

相关知识

为了完成本关任务,你需要掌握:分治法。

题目

 输入 n 个整数和一个一个正整数k (1<=k<=n),输出这些整数从小到大排序后的第k个(例如,k=1就是最小值)。n<=10 

7

分析

备注(在数据结构算法中,解决问题的方法有很多,但是,请转变一个观念。不是达到目的就可以了。要考虑时间效率。如果在最短的时间内完成任务。)

选择第k大的数,最容易想到的方法是先排序,然后直接输出下标为k-1的元素(别忘了C语言中数组下标从0开始),但10 

7

 的规模即使对于O(nlogn)的算法来说较大。有没有更快的方法呢?

  答案是肯定有的。假设在快速排序的“划分”结束后,数组A[l···r]被分成了A[l···q]和A[q,r],则可以根据左边的元素个数q-l+1和 k的大小关系只在左边或者右边递归求解。

时间复杂度

可以证明,在期望意义下,程序的时间复杂度为O(n)。

快排科普

快速排序的时间复杂度为:最坏情况O(n 

2

 );平均情况O(nlogn),但实践中几乎不可能达到最坏情况,效率非常高。根据快速排序思想,可以在平均O(n)时间内选出数组中第 k 大的元素。

编程要求

根据提示,在右侧编辑器补充代码,选出序列中第k大的元素。

测试说明

输入数据:

    三行。第一行输入数字n。(有n个数待排序);

    第二行。有n个数。(待排序的n个数)。

   第三行,k值。

输出数据:

    一个数。为n给数中第k位的数(数据从小到大)。

平台会对你编写的代码进行测试:

测试输入:

4

3 1 2 4

3

预期输出:

3

测试输入:

7

4 7 5 3 6 2 1

4

预期输出:

4

开始你的任务吧,祝你成功!

 

#include<stdio.h>
int partion(int a[],int l,int r)
{
             int p,j,temp;
             int s=l;
             int g;
             p = r;
// p = a[length];
               
           for (j = l; j<=p; j++)
                 
    {
                     while (1)
                      {
                         if (a[s] <a[p])
                          {
                             s = s + 1;
                                          //把s移到大于准值的位置
                           
            }
                        else
                            break;
                       
        }
                 if (a[j] <=a[p]&&j>s)
                      {
                         temp = a[s];
                         a[s] = a[j];
                        a[j] = temp;
                                              //检测到小于准值的位置进行交换
                         
        }
                 
    }
                g=s+1;
                                 //对最终位置进行标记
              //  temp = a[s];
               // a[s] = a[p];
                //a[p] = temp;
                return g;
}
int main()
{
    int b[100000],i,l1,r1,k1=-1;
    int n,k,h;
    scanf("%d", &n);
    l1=0,r1=n-1;
           for(i=0; i<n; i++)
        scanf("%d", &b[i]);
    scanf("%d",&k);
    while (1)
    {
        h=k1;
        k1= partion(b,l1,r1);

        if(k1==k||h==k1)
        {
            printf("%d",b[k-1]);
            for(int i=0; i<n; i++) printf(" %d",b[i]);
            break;
        }
//break;
        if(k1>k)
        {
               
               r1=k1-2;
               continue;
        }
        if(k1<k)
        {
                l1=k1-1;
               
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值