在一个由n个元素组成的集合中,第i个“顺序统计量(order statistic)”是该集合中第i小的元素。例如,在一个由n个元素组成的集合中,最小值是第1个顺序统计量,最大值是第n个顺序统计量。而“中位数(median)”总是出现在low((n+1)/2)或者high((n+1)/2)处,其中low是向下取整(“下中位数”),high是向上取整(“上中位数”),当n为奇数的时候,只有“下中位数”,而n为偶数的时候,同时有“下中位数”和“上中位数”。

选择问题的定义如下。
  输入:一个包含n个不同的数的集合A和一个数i,i属于范围[1,n]
  输出:集合A中的一个元素x,x恰好大于A中的其他i-1个元素

通过排序的方法可以解决这个问题,比如堆排序、归并排序。时间可以达到O(n*lg(n))

 

下面讨论一个实用的算法,平均情况下运行时间为O(n)

  此程序利用了快速排序的partition子程序(随机选择pivot的版本),因为partition总是把比pivot小的划分到左边,比pivot大的划分到右边,所以利用这一点(但是randomizedSelect不会向快速排序一样递归地处理划分出来的两边,而是只处理左边或者右边,因此要更快一些)完成选择。

  此算法平均性能比较好,因为是随机化的划分,不会有哪一组特定的输入导致其最坏情况的发生。

  平均时间是O(n),最坏时间是O(n^2)

实现代码如下:

 package algorithms;

 import java.util.Arrays;
import java.util.Random;
public class SelectionProblem { //static StringBuilder logger = new StringBuilder(); // debug
//static String NEWLINE = "\n"; // debug /**
* @param a the array
* @param low the lower bound (inclusive)
* @param high the upper bound (exclusive)
* @param i indicate that the i-th order statistic is our target, i starts from 1
* @return the i-th order statistic
* */
public static <T extends Comparable<T>>
T randomizedSelect(T[] a, int low, int high, int i) {
--high; // high the upper bound (exclusive)
return _randomizedSelect(a, low, high, i);
} private static <T extends Comparable<T>>
T _randomizedSelect(T[] a, int low, int high, int i) {
if (low == high) {
return a[low]; // target found
}
// else, partition
int pivot = randomizedPartition(a, low, high);
int k = pivot - low + 1;
if (k == i) { // if pivot is our target
return a[pivot];
} else if (k > i) { // if pivot is too large
return _randomizedSelect(a, low, pivot-1, i);
} else { // if pivot is too small
return _randomizedSelect(a, pivot+1, high, i-k);
}
} private static <T extends Comparable<T>>
int randomizedPartition(T[] a, int low, int high) {
int pivotIndex = randomIndex(low, high+1);
// logger.append("pivotIndex:"+pivotIndex+NEWLINE); // debug
return Partition.doPartition(a, low, high+1, pivotIndex);
} private static final Random random = new Random();
// low (inclusive), high (exclusive)
private static int randomIndex(int low, int high) {
if (high==low) {
return low;
}
return random.nextInt(high-low) + low;
} // test
public static void main(String[] args) {
Integer[] a = new Integer[]{29, 36, 44, 12, 29, 24, 28, 74, 54, 56};
System.out.println(Arrays.toString(a));
Integer result = SelectionProblem.randomizedSelect(a, 0, a.length, 10);
//if (result != 36) { // debug
// System.out.println(logger); // debug
//} // debug
System.out.println("result:"+result);
//System.out.println(Arrays.toString(a)); // debug
QuickSort.sort(a, 0, a.length);
System.out.println(Arrays.toString(a));
} }

最新文章

  1. ucos实时操作系统学习笔记——任务间通信(消息)
  2. StringUtils工具类
  3. FDCT变换 公式法
  4. SPSS数据分析—加权最小二乘法
  5. PHP数组去重..............过滤字段
  6. [转]深入理解jQuery插件开发
  7. N - Marriage Match II - HDU 3081(最大流)
  8. 关于jquery的each的操作;
  9. [转]Linux(centOS6.5)下SVN的安装、配置及开机启动
  10. Java批处理操作
  11. peoplesoft function PSTREENODE 通过 deptid 获得部门树 一级部门 名称
  12. POJ 1502 MPI Maelstrom(模板题——Floyd算法)
  13. Xcode7.2如何真机调试iOS 9.3的设备
  14. 认识MyBatis-总述
  15. NC 创建表空间数据库
  16. SQL Server 2008 R2 下如何清理数据库日志文件
  17. ASP.Net Core中使用jquery-ajax-unobtrusive替换Ajax.BeginForm
  18. 看懂MSSQL执行计划,分析SQL语句执行情况
  19. 第七周 linux如何装载和启动一个可执行文件
  20. docker端口映射,批量删除容器

热门文章

  1. Struts的线程安全
  2. KD-Tree复习笔记(BZOJ1941 &amp; BZOJ2648 &amp; BZOJ4066)
  3. [USACO09MAR]Cleaning Up
  4. 数值计算方法 | C语言实现几个数值计算方法(实验报告版)
  5. 说一说ST表 讲一讲水题
  6. Ubuntu 16.04使用“从互联网自动获取”时间无法写入硬件BIOS的奇怪问题
  7. yolo.v2 darknet19结构
  8. solr 常用命令
  9. Android - 标准VideoView播放演示样例
  10. Linux alias理解及设置