在线性级别时间内找出无序序列中的第k个元素
在一个无序序列中找出第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个元素的更多相关文章
- [PY3]——找出一个序列中出现次数最多的元素/collections.Counter 类的用法
问题 怎样找出一个序列中出现次数最多的元素呢? 解决方案 collections.Counter 类就是专门为这类问题而设计的, 它甚至有一个有用的 most_common() 方法直接给了你答案 c ...
- 如何寻找无序数组中的第K大元素?
如何寻找无序数组中的第K大元素? 有这样一个算法题:有一个无序数组,要求找出数组中的第K大元素.比如给定的无序数组如下所示: 如果k=6,也就是要寻找第6大的元素,很显然,数组中第一大元素是24,第二 ...
- 寻找无序数组中的前k大元素
题目描述 以尽可能小的代价返回某无序系列中的两个最大值,当有重复的时设置某种机制进行选择. 题解 首先要考虑的是重复的数的问题. A.不处理重复数据方法:在处理第k大的元素时不处理重复的数据,也就是将 ...
- 找出N个数中最小的k个数问题(复杂度O(N*logk))
这是一个经典的算法题,下面给出的算法都在给定的数组基础上进行,好处时不用分配新的空间,坏处是会破坏原有的数组,可以自己分配新的空间以避免对原有数组的破坏. 思路一 先直接排序,再取排序后数据的前k个数 ...
- 【python cookbook】【数据结构与算法】12.找出序列中出现次数最多的元素
问题:找出一个元素序列中出现次数最多的元素是什么 解决方案:collections模块中的Counter类正是为此类问题所设计的.它的一个非常方便的most_common()方法直接告诉你答案. # ...
- 【python cookbook】找出序列中出现次数最多的元素
问题 <Python Cookbook>中有这么一个问题,给定一个序列,找出该序列出现次数最多的元素.例如: words = [ 'look', 'into', 'my', 'eyes', ...
- Entity Framework 6 Recipes 2nd Edition(9-3)译->找出Web API中发生了什么变化
9-3. 找出Web API中发生了什么变化 问题 想通过基于REST的Web API服务对数据库进行插入,删除和修改对象图,而不必为每个实体类编写单独的更新方法. 此外, 用EF6的Code Fri ...
- Python算法每日一题--001--给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找出那个只出现了一次的元素. 说明: 你的算法应该具有线性时间复杂度. 你可以不使用额外空间来实现吗? 示例 1: 输入: [ ...
- 一个N*M的矩阵,找出这个矩阵中所有元素的和不小于K的面积最小的子矩阵
题目描述: 一个N*M的矩阵,找出这个矩阵中所有元素的和不小于K的面积最小的子矩阵(矩阵中元素个数为矩阵面积) 输入: 每个案例第一行三个正整数N,M<=100,表示矩阵大小,和一个整数K 接下 ...
随机推荐
- laravel5的坑
以此记录学习laravel的一些问题 问题:laravel转移文件夹到另外一pc或者环境后访问出现500 设置权限为777 问题: 设置路由后页面总是404 not found 解决:需要在apach ...
- 188. Best Time to Buy and Sell Stock IV
题目: 链接: 题解: 测试: Reference:
- 123. Best Time to Buy and Sell Stock III
题目: Say you have an array for which the ith element is the price of a given stock on day i. Design a ...
- 转:JavaScript中函数与对象的关系
来自:http://www.nowamagic.net/javascript/js_RelationOfFunctionAndObject.php 在ajax兴起以前,很多人写JavaScript可以 ...
- mmap
http://www.360doc.com/content/11/0830/10/1964482_144428042.shtml
- shorter concat [reverse longer]
shorter concat [reverse longer] Description: Given 2 strings, a and b, return a string of the form: ...
- poj 3253 Fence Repair (哈夫曼树 优先队列)
题目:http://poj.org/problem?id=3253 没用long long wrong 了一次 #include <iostream> #include<cstdio ...
- POJ 2112 Optimal Milking (Floyd+二分+最大流)
[题意]有K台挤奶机,C头奶牛,在奶牛和机器间有一组长度不同的路,每台机器每天最多能为M头奶牛挤奶.现在要寻找一个方案,安排每头奶牛到某台机器挤奶,使得C头奶牛中走过的路径长度的和的最大值最小. 挺好 ...
- datagrid中需要填写长文本,扩展的textarea
$.extend($.fn.datagrid.defaults.editors, { textarea: {//textarea就是你要自定义editor的名称 init: function(cont ...
- 【转】Android异步消息处理机制完全解析,带你从源码的角度彻底理解
原文网址:http://blog.csdn.net/guolin_blog/article/details/9991569 转载请注明出处:http://blog.csdn.net/guolin_bl ...