问题描述:给定线性序集中n个元素和一个整数k,1≤k≤n,要求找出这n个元素中第k大的元素,(这里给定的线性集是无序的)。

  其实这个问题很简单,直接对线性序列集qsort,再找出第k个即可。但是这样的时间复杂度就是qsort的时间复杂度O(nlogn)。有没有更快的方法呢?看到网上有一种解法是采取了快排的思路,但是稍微坐了些改动,然后时间复杂度能够接近O(n)。因为最近刚刚写了快排的实现,所以在这我就再把这个实现一次吧。

  解题思路:与快排不同的是,这里只对划分出来的其中一组进行递归处理。任意选定一个pivotIndex,pivotValue = arr[pivotIndex]。经过一次划分后,pivotValue存储在storeIndex的位置,storeIndex把数组划分为两部分。比pivoteValue大的在前面,比pivotValue小的存储在后面(此时前后两部分是没有排好序的)。那么storeIndex位置的pivotValue就肯定是第storeIndex大的数。然后用K于storeIndex比较,如果K<storeIndex,那么说明第K大一定在右边,那么再对右边进行划分即可。如果K>storeIndex,那么说明第K大一定在左边,那么再对左边进行划分。然后递归,最后就可以得到第K大。

#include <stdio.h>

void swap(int *a, int *b)
{
int tmp;
tmp = *a;
*a = *b;
*b = tmp;
} int partition(int arr[], int left, int right, int pivotIndex)
{
int storeIndex = left;
int pivotValue = arr[pivotIndex];
int i; swap(&arr[pivotIndex],&arr[right]); for (i = left; i < right; i ++)
{
if (arr[i] > pivotValue)
{
swap(&arr[i],&arr[storeIndex]);
storeIndex++;
}
}
swap(&arr[storeIndex],&arr[right]);
return storeIndex;
} int findKMax(int arr[], int left, int right, int k)
{
int nRet;
int pivotIndex = left + ; nRet = partition(arr,left,right,pivotIndex);
if (nRet < k)
{
return findKMax(arr,nRet+,right,k);
}
else if (nRet > k)
{
return findKMax(arr,left,nRet-,k);
} return nRet;
} int main()
{
int i,k,nRet;
int arr[] = {,,,,,,,}; scanf("%d",&k);
nRet = findKMax(arr,,,k-); printf("The Kth Max Number locate in %d is :%d\n",nRet,arr[nRet]);
for (i = ; i < ; i++)
{
printf("%3d",arr[i]);
}
return ;
} // :

  萧萧空间列出了很多种寻找第K大数的算法。

第二次实现该算法:

#include <stdio.h>

void swap(int arr[], int i, int j)
{
int tmp; tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
} int partition(int arr[], int left, int right)
{
int value = arr[left];
int p_insert,p_cmp; swap(arr,left,right);
p_insert = p_cmp = left; while (p_cmp < right)
{
if (arr[p_cmp] < value)
{
swap(arr,p_insert,p_cmp);
p_insert++;
}
p_cmp++;
}
swap(arr,p_insert,right); return p_insert;
} void max_k(int arr[], int left, int right,int k)
{
int ret = partition(arr,left,right);
if (ret == k) return;
else if (ret < k)
ret = partition(arr,ret+,right);
else
ret = partition(arr,left,ret);
} int main()
{
int arr[] = {,,,,,,,,};
int i,k = ; max_k(arr,,,k); for (i = ; i < k; i++)
{
printf("%d ",arr[i]);
}
printf("\n"); return ;
} // :

分治算法--寻找第k大数的更多相关文章

  1. 蓝桥杯 算法训练 区间k大数查询(水题)

    算法训练 区间k大数查询 时间限制:1.0s   内存限制:256.0MB 问题描述 给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个. 输入格式 第一行包含一个数n,表示序列长度. ...

  2. 算法训练 区间k大数查询

    http://lx.lanqiao.org/problem.page?gpid=T11 算法训练 区间k大数查询   时间限制:1.0s   内存限制:256.0MB        问题描述 给定一个 ...

  3. 蓝桥杯--算法训练 区间k大数查询

                                                                                 算法训练 区间k大数查询   时间限制:1.0 ...

  4. 算法训练 区间K大数

    算法训练 区间k大数查询 时间限制:1.0s   内存限制:256.0MB 问题描述 给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个. 输入格式 第一行包含一个数n,表示序列长度. ...

  5. 蓝桥杯算法训练 区间k大数查询

    算法训练 区间k大数查询   问题描述 给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个. 输入格式 第一行包含一个数n,表示序列长度. 第二行包含n个正整数,表示给定的序列. 第三个 ...

  6. P3290 寻找第K大数

    描述 寻找第K大数 N个小朋友在一起做游戏.每个小朋友在自己的硬纸板上写一个数,然后同时举起来.接着,小y老师提一个问题,看哪个小朋友先抢答出来.问题是:在这N个数中,第K大的是哪个数?请你编程完成. ...

  7. Java实现 蓝桥杯 算法训练 区间k大数

    算法训练 区间k大数查询 时间限制:1.0s 内存限制:256.0MB 问题描述 给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个. 输入格式 第一行包含一个数n,表示序列长度. 第二 ...

  8. 算法准备-分治算法解决第k位数的线性查找

    由作业士兵排队问题引出的 在一个划分成网格的操场上,n个士兵散乱地站在网格点上.网格点由整数最表(x,y)表示.士兵可以沿着网格边上.下.左.右移动一步,但在同一时刻一个网格上只能有一名士兵.按照军官 ...

  9. 蓝桥网试题 java 算法训练 区间k大数查询

    -------------------------------------------------------------------------- 数组也有sort方法 尽量把输入和操作分开写 -- ...

随机推荐

  1. 更改 AWS RDS mysql时区 -摘自网络

    AWS RDS AWS上搭建数据库的时候,不是DB on EC2就是RDS,但是选择RDS时,Timezone怎么处理? 「面向全球提供的AWS来讲理所当然的是UTC」,而RDS也不是例外.把服务器迁 ...

  2. CentOS 7 设置iptables防火墙开放proftpd端口

    由于ftp的被动模式是这样的,客户端跟服务器端的21号端口交互信令,服务器端开启21号端口能够使客户端登录以及查看目录.但是ftp被动模式用于传输数据的端口却不是21,而是大于1024的随机或配置文件 ...

  3. Kubernetes的系统架构与设计理念

    Kubernetes与云原生应用简介 随着Docker技术的发展和广泛流行,云原生应用和容器调度管理系统也成为IT领域大热的词汇.事实上,云原生应用的思想,在Docker技术火爆之前,已经由云计算技术 ...

  4. 探寻main函数的“标准”写法,以及获取main函数的参数、返回值

    main函数表示法        很多同学在初学C或者C++时,都见过各种各样的main函数表示法: main(){/*...*/} void main(){/*...*/} int main(){/ ...

  5. Chunk

    Chunk是一系列语句,Lua执行的每一块语句,比如一个文件或者交互模式下的每一行都是一个Chunk. 每个语句结尾的分号(;)是可选的,但如果同一行有多个语句最好用:分开 a = 1   b = a ...

  6. OpenStack OVS GRE/VXLAN

    https://www.jianshu.com/p/0b52de73a4b3 OpenStack OVS GRE/VXLAN网络 学习或者使用OpenStack普遍有这样的现象:50%的时间花费在了网 ...

  7. VS2015终极卸载方法

    今天打开VS2015发现出问题了,总是停止响应,去控制面板里卸载结果像下面这样,卸载出错!于是我有开始折腾了,重新安装一遍然后,还是有问题,在卸载还是出错于是我决定通过安装介质卸载,结果,悲剧的是,启 ...

  8. (原创)C++11改进我们的程序之简化我们的程序(二)

    这次要讲的是:C++11如何通过组合函数来简化我们的程序.关于组合函数,大家可能对这个概念有点陌生.组合函数是将N个一元函数组成一种更复杂的函数,每个函数的返回值作为参数传给下一个函数,直到传到最后一 ...

  9. Android Http 下载

    在安卓中,可以直接用java的java.net.URL包访问网络下载数据.不同的是,安卓程序需要权限,需要在AndroidManifest.xml文件中声明权限 <!-- 网络权限 --> ...

  10. 【教程】minicom使用教程

    简介 Linux下的Minicom的功能与Windows下的超级终端功能相似,可以通过串口控制外部的硬件设备.适于在linux通过超级终端对嵌入式设备行管理.同样也可以使用minicom对外置Mode ...