选取第K大数的快速选择算法和注意事项
快速选择算法,是一种能在大致O(N)的时间内选取数组中第k大或者k小的算法.其基本思路与快速排序算法类似,也是分治的思想.
其实这个算法是个基础算法,但是不常用,所以今天编的时候错了POJ2388,才有了这篇文章.
- 执行Partition算法(就是那个快排里将区间内所有数划分为小的一部分和大的一部分的过程)
- 判断第k大的数是在小的部分还是大的部分
- 递归,直到区间足够小,返回结果
下面几段代码,尤其要注意的是
while(i<j)
还是
while(i<=j)
程序1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
/*
Program:快速选择算法样例
Author:Comzyh
*/
#include <cstdio>
int array[10000],temp;
int N,K;
int QuickSelect(int arr[],int b,int e,int k);
int main()
{
scanf("%d%d",N,K);
for (int i=1;i<=N;i++)
scanf("%d",array[i]);
printf("The k th :%d\n",QuickSelect(array,1,N,K));
}
int QuickSelect(int arr[],int b,int e,int k)
{
int i=b,j=e,mid=arr[(i+j)>>1];
while (i<=j)//注意,小于等于
{
while (arr[i]<mid)i++;
while (arr[j]>mid)j--;
if (i<=j)
{
temp=arr[i];arr[i]=arr[j];arr[j]=temp;
i++;j--;
}
}
if (b<j k<=j)return QuickSelect(arr,b,j,k);//分治
if (i<e k>=i)return QuickSelect(arr,i,e,k);
return arr[k];//如果不属于任何一方,就结束,返回
}
|
不过,就是这样一个简单的算法,今天也出了点错误,本来我是用用了多少年的快排改的,就像下面这段代码
程序2:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
/*
Program:快速排序算法样例
Author:Comzyh
*/
#include <cstdio>
int array[10000],temp;
int N,K;
int QuickSort(int arr[],int b,int e);
int main()
{
scanf("%d",N);
for (int i=1;i<=N;i++)
scanf("%d",array[i]);
QuickSort(array,1,N);
for (int i=1;i<=N;i++)
printf("%d\n",array[i]);
}
int QuickSort(int arr[],int b,int e)
{
int i=b,j=e,mid=arr[(i+j)>>1];
while (i<j)//注意,小于
{
while (arr[i]<mid)i++;
while (arr[j]>mid)j--;
if (i<=j)
{
temp=arr[i];arr[i]=arr[j];arr[j]=temp;
i++;j--;
}
}
if (b<j)QuickSort(arr,b,j);
if (i<e)QuickSort(arr,i,e);
}
|
几乎一模一样,但是下面这样写就是是错的
程序3:
1
2
3
4
5
6
7
8
9
10
11
|
int QuickSelect(int arr[],int b,int e,int k)
{
int i=b,j=e,mid=arr[(i+j)>>1];
while (i<j)//注意,小于
{
....
}
if (b<j k<=j)return QuickSelect(arr,b,j,k);//分治
if (i<e k>=i)return QuickSelect(arr,i,e,k);
return arr[k];//如果不属于任何一方,就结束,返回
}
|
而这样写是对的
程序4:
1
2
3
4
5
6
7
8
9
10
11
|
int QuickSelect(int arr[],int b,int e,int k)
{
int i=b,j=e,mid=arr[(i+j)>>1];
while (i<j)//注意,小于
{
....
}
if (b<j k<=j)QuickSelect(arr,b,j,k);//没有Return
if (i<e k>=i) QuickSelect(arr,i,e,k);
return arr[k];//如果不属于任何一方,就结束,返回
}
|

- 按照错误的方法(程序3)执行(如图(3)),函数会在闭区间[1,4]中寻找答案,这样是错误的,因为arr[5]=3不在这个区间内
- 按照程序1中的方法执行,j会自减1,因为不满足i<=j(i=4,j=3)然后会在闭区间[4,6]中递归(如图(4)),寻找答案,这样是正确的
- 按照程序4中的方法执行,QuickSelect(1,4,4)执行完之后arr[4]=6,这样,再执行QuickSelect(4,6,4)时,程序会返回正确的结果
选取第K大数的快速选择算法和注意事项的更多相关文章
- 蓝桥杯 算法训练 区间k大数查询(水题)
算法训练 区间k大数查询 时间限制:1.0s 内存限制:256.0MB 问题描述 给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个. 输入格式 第一行包含一个数n,表示序列长度. ...
- 算法训练 区间k大数查询
http://lx.lanqiao.org/problem.page?gpid=T11 算法训练 区间k大数查询 时间限制:1.0s 内存限制:256.0MB 问题描述 给定一个 ...
- POJ 2388 Who's in the Middle (快速选择算法:O(N)求数列第K大)
[题意]求数列中间项. ---这里可以扩展到数列第K项. 第一次做的时候直接排序水过了= =--这一次回头来学O(N)的快速选择算法. 快速选择算法基于快速排序的过程,每个阶段我们选择一个数为基准,并 ...
- 蓝桥杯--算法训练 区间k大数查询
算法训练 区间k大数查询 时间限制:1.0 ...
- 普林斯顿大学算法课 Algorithm Part I Week 3 求第K大数 Selection
问题 给定N个元素的数组,求第k大的数. 特例当k=0时,就是求最大值,当k=N-1时,就是求最小值. 应用顺序统计求top N排行榜 基本思想 使用快速排序方法中的分区思想,使得a[k]左侧没有更小 ...
- 算法训练 区间K大数
算法训练 区间k大数查询 时间限制:1.0s 内存限制:256.0MB 问题描述 给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个. 输入格式 第一行包含一个数n,表示序列长度. ...
- 分治算法--寻找第k大数
问题描述:给定线性序集中n个元素和一个整数k,1≤k≤n,要求找出这n个元素中第k大的元素,(这里给定的线性集是无序的). 其实这个问题很简单,直接对线性序列集qsort,再找出第k个即可.但是这样的 ...
- 蓝桥杯算法训练 区间k大数查询
算法训练 区间k大数查询 问题描述 给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个. 输入格式 第一行包含一个数n,表示序列长度. 第二行包含n个正整数,表示给定的序列. 第三个 ...
- Java实现 蓝桥杯 算法训练 区间k大数
算法训练 区间k大数查询 时间限制:1.0s 内存限制:256.0MB 问题描述 给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个. 输入格式 第一行包含一个数n,表示序列长度. 第二 ...
随机推荐
- vue+element UI如何导出excel表
导出excel表应按如下规则 首先要先安装如下依赖 npm install --save xlsx npm install --save file-saver 接下在在你的代码中去引用这两个 impo ...
- Ubuntu美化
Ubuntu美化 觉得ubuntu18.04的界面太丑了,所以决定美化一下. 整了好长时间特别费事.所以写个随笔记录一下. 安装gnome-tweak-tool和gnome-shell-extensi ...
- PAT 乙级 1011
题目 题目地址:PAT 乙级 1011 思路 这道题的比较坑的地方在于给定数据的范围 int 类型的数据大小是[-2^31 , 2^31 -1] 即 [-2147483648,2147483647] ...
- [CODEVS] 2189 数字三角形W
数字三角形 要求走到最后mod 100最大 可达性DP(好像是这样叫) 用bool数组f[i][j][k]表示 位置(i,j)能否得到k(mod 100意义下) 转移条件 f[i][j][k]=f[i ...
- (31)zabbix Aggregate checks聚合检测
概述 aggregate checks是一个聚合的检测,例如我想知道某个组的host负载平均值,硬盘剩余总量,或者某几台机器的这些数据,简单的说,这个方法就是用来了解一个整体水平,而不需要我们一台台看 ...
- DOM、SAX、JDOM、DOM4J以及PULL在XML文件解析中的工作原理以及优缺点对比
1. DOM(Document Object Model)文档对象模型1. DOM是W3C指定的一套规范标准,核心是按树形结构处理数据,DOM解析器读入XML文件并在内存中建立一个结构一模一样的&qu ...
- linux相关技术
1.查询服务器tcp连接状态及连接数 netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
- UIDatePicker 显示时间和打印时间不一样
默认是时区为0,如下格式化一下就好啦 UIDatePicker *datePiker = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 100, ...
- php 上传文件名出现乱码
想必很多朋友在进行utf8编码的php开发上传功能的时候,都会遇到这样的一个问题,就是上传中文文件名的文件时,文件名会变成乱码,其实我们可以用iconv函数对文件名进行重新编码就解决问题了 可能会有不 ...
- Leetcode 410.分割数组的最大值
分割数组的最大值 给定一个非负整数数组和一个整数 m,你需要将这个数组分成 m 个非空的连续子数组.设计一个算法使得这 m 个子数组各自和的最大值最小. 注意:数组长度 n 满足以下条件: 1 ≤ n ...