在一个无序序列中找出第k个元素,对于k很小或者很大时可以采取特殊的方法,比如用堆排序来实现 。但是对于与序列长度N成正比的k来说,就不是一件容易的事了,可能最容易想到的就是先将无序序列排序再遍历即可找出第k个元素。由于任何基于比较的排序算法不可能用少于Θ(N lgN)次比较来实现将所有元素排序,所以采用排序的方法的时间复杂度是线性对数级别的。

我们可以借鉴快速排序中将序列划分的思想来实现平均情况下线性级别的算法,算法实现如下:

 public class KthElement {

     private static void exch(Comparable[] a, int i, int j)
{
Comparable swap = a[i];
a[i] = a[j];
a[j] = swap;
} private static boolean less(Comparable a, Comparable b)
{
return a.compareTo(b) < 0;
} private static int partition(Comparable[] a, int lo, int hi)
{
int i = lo;
int j = hi + 1;
Comparable v = a[lo];
while(true)
{
while(less(a[++i], v)) if(i == hi) break;
while(less(v, a[--j]));
if(i >= j) break;
exch(a, i, j);
}
exch(a, lo, j);
return j;
} public static Comparable select(Comparable[] a, int k)
{
int lo = 0;
int hi = a.length - 1;
while(hi > lo)
{
int j = partition(a, lo, hi);
if(j == k) break;
else if(j > k) hi = j - 1;
else if(j < k) lo = j + 1;
}
return a[k];
}
public static void main(String[] args) {
Integer[] ints = {5, 3, 1, 4, 2};
int find = (int) select(ints, 2);
System.out.println(find);
} }

在select方法中,使用partition方法将序列划分。如果k = j,问题就已经解决了; 如果k < j,就继续切分左字数组(令 hi = j - 1);如果k > j,就继续切分右子数组(令lo = j + 1)。该循环保证了lo左边的元素都小于等于a[lo...hi], 而hi右边的元素都大于等于a[lo...hi],我们不断切分直到数组中只剩下第k个元素。为何这个的时间复杂度是线性级别的,证明很复杂,在此给出理想情况下的简易证明。假设每次切分都从中间切分,则所有的比较次数为(N + N/2 + N/4 + N/8 +...)直到找到k,很显然这个和小于2N。平均情况下的复杂度为Θ( 2N + 2Kln(N/K) + 2(N - K)ln(N/(N-K)) )。当K = N/2时,复杂度为Θ((2 + 2ln2)N)。

在线性级别时间内找出无序序列中的第k个元素的更多相关文章

  1. [PY3]——找出一个序列中出现次数最多的元素/collections.Counter 类的用法

    问题 怎样找出一个序列中出现次数最多的元素呢? 解决方案 collections.Counter 类就是专门为这类问题而设计的, 它甚至有一个有用的 most_common() 方法直接给了你答案 c ...

  2. 如何寻找无序数组中的第K大元素?

    如何寻找无序数组中的第K大元素? 有这样一个算法题:有一个无序数组,要求找出数组中的第K大元素.比如给定的无序数组如下所示: 如果k=6,也就是要寻找第6大的元素,很显然,数组中第一大元素是24,第二 ...

  3. 寻找无序数组中的前k大元素

    题目描述 以尽可能小的代价返回某无序系列中的两个最大值,当有重复的时设置某种机制进行选择. 题解 首先要考虑的是重复的数的问题. A.不处理重复数据方法:在处理第k大的元素时不处理重复的数据,也就是将 ...

  4. 找出N个数中最小的k个数问题(复杂度O(N*logk))

    这是一个经典的算法题,下面给出的算法都在给定的数组基础上进行,好处时不用分配新的空间,坏处是会破坏原有的数组,可以自己分配新的空间以避免对原有数组的破坏. 思路一 先直接排序,再取排序后数据的前k个数 ...

  5. 【python cookbook】【数据结构与算法】12.找出序列中出现次数最多的元素

    问题:找出一个元素序列中出现次数最多的元素是什么 解决方案:collections模块中的Counter类正是为此类问题所设计的.它的一个非常方便的most_common()方法直接告诉你答案. # ...

  6. 【python cookbook】找出序列中出现次数最多的元素

    问题 <Python Cookbook>中有这么一个问题,给定一个序列,找出该序列出现次数最多的元素.例如: words = [ 'look', 'into', 'my', 'eyes', ...

  7. Entity Framework 6 Recipes 2nd Edition(9-3)译->找出Web API中发生了什么变化

    9-3. 找出Web API中发生了什么变化 问题 想通过基于REST的Web API服务对数据库进行插入,删除和修改对象图,而不必为每个实体类编写单独的更新方法. 此外, 用EF6的Code Fri ...

  8. Python算法每日一题--001--给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素

    给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找出那个只出现了一次的元素. 说明: 你的算法应该具有线性时间复杂度. 你可以不使用额外空间来实现吗? 示例 1: 输入: [ ...

  9. 一个N*M的矩阵,找出这个矩阵中所有元素的和不小于K的面积最小的子矩阵

    题目描述: 一个N*M的矩阵,找出这个矩阵中所有元素的和不小于K的面积最小的子矩阵(矩阵中元素个数为矩阵面积) 输入: 每个案例第一行三个正整数N,M<=100,表示矩阵大小,和一个整数K 接下 ...

随机推荐

  1. CF339

    C. Xenia and Weights 有1...10k的砝码,在天枰上,左右轮流放置砝码,要求之后左右轮流比另一侧重量要大,要求相邻两次砝码不能相同. 解题报告给出(i,j,k)表示balance ...

  2. WCF 下的windows服务的安装卸载

    安装:启动vs2010(如果是win2008要以管理员来启动)命令:installutil demo.exe 卸载:先在服务里停止这个服务,然后启动vs2010(如果是win2008要以管理员来启动) ...

  3. 转载:最小生成树-Prim算法和Kruskal算法

    本文摘自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/30/2615542.html 最小生成树-Prim算法和Kruskal算法 Prim算 ...

  4. poj 2965 The Pilots Brothers' refrigerator枚举(bfs+位运算)

    //题目:http://poj.org/problem?id=2965//题意:电冰箱有16个把手,每个把手两种状态(开‘-’或关‘+’),只有在所有把手都打开时,门才开,输入数据是个4*4的矩阵,因 ...

  5. Codeforces 364A - Matrix

    原题地址:http://codeforces.com/problemset/problem/364/A 题目大意: 给定一个数字a(0 ≤ a ≤ 109)和一个数列s(每个数都是一位,长度不超过40 ...

  6. WindowsPhone8SDK重装后设计器加载异常的处理办法

    Close all running instances of Visual Studio 2012 start cmd.exe (as admin/elevated) cd /d %windir%\i ...

  7. entity framework 查询

    1.简单查询: SQL: SELECT * FROM [Clients] WHERE Type=1 AND Deleted=0 ORDER BY ID EF: //Func形式 var clients ...

  8. WinCE发展史

    Windows CE概述 WindowsCE是微软公司嵌入式.移动计算平台的基础,它是一个开放的.可升级的32位嵌入式操作系统,是基于掌上型电脑类的电子设备操作系统,它是精简的Windows 95,W ...

  9. 【转】Android底层库和程序

    原文网址:http://blog.csdn.net/louiswangbing/article/details/6616202 Android底层库和程序 1.     本地实现的基本结构 Andro ...

  10. jQuery 属性操作 - val() 方法

    val() 方法返回或设置被选元素的值. 元素的值是通过 value 属性设置的.该方法大多用于 input 元素. 如果该方法未设置参数,则返回被选元素的当前值. <html> < ...