`

★经典问题—元素选择问题

阅读更多

元素选择问题   : 给定线性序集中n个元素和一个整数k(1<=k<=n),要求找出这n个元素中第k小的元素(第n-k大)。 这一问题可以演化成找最大最小值、找中位数等。

 

最简单思想:如果是直接找最大最小值,则可以通过N次比较来完成,其时间复杂度为O(N),空间复杂度为O(1)。除此之外,对于一般的k值,可以考虑对序列N先进行排序,然后直接定位第k个位置上的数即可。时间复杂度最好为O(N*logN)。

 

改进思想:

(1) 在某些特殊情况下,是很容易设计出O(N)的算法。比如最大最小值的时候。

      如果k<=n/logn 找第k小的元素。我们可以通过堆排序的方法。 首先建立小顶堆,其时间复杂度为O(N)。然后每次输出堆顶元素(当前堆的最小值)后调整堆顶,其时间复杂度为O(logN)。循环k次,当第k次输出堆顶时结束。这样的时间复杂度为O(N+k*logN),  而k<=n/logn,即k接近于常数,则时间复杂度近似为O(N)。

      如果k>=n-n/logn 找第k小的元素。同理可以建立一个(n-k)次输出的大顶堆即可。

      当k的大小靠近n的两侧时,比如n=10,k=2或8。我们可以同归堆排序来达到近似O(N)的时间复杂度。

 

(2) 但一般的k值,特别是中位数的选择问题似乎就比上一种情况要难了。但事实上,我们仍然可以在O(n)的时间内解决。

      可以考虑快排的分治算法,对N序列进行一次Partition。与快排不同的是,每次只对划分后的一个子数组进行处理。其算法代码如下:

//在a数组中选择第k小的数
Type select(Type a[], int low, int high, int k){
       //找到的第k小的数
       if(low==high) return a[low];
       //一次选择划分,此时a[low..mid-1]<a[mid]<a[mid+1..high]
       int mid=partition(a,low, high);
       int midSize=mid-low+1;
       if(k<=midSize) return select(a, low, mid, k);
       else return select(a, mid+1, high, k-midSize);
}

       从代码中很容易看出,在最坏情况下,这种算法和快排有着一样的蜕化现象,需要O(N^2)时间复杂度。但是在一般情况下,平均性能上可以保证近似O(N)的时间复杂度。 如果想要克服最坏情况,其基准(快排中的枢轴)的选择可以进行优化。使得基准所划分出来的两个子数组的长度至少为原数组长度的x倍(0<x<1)。具体优化策略可以参见《【JDK优化策略】java.util.Arrays的排序研究 》中的快排优化。

 

 

分享到:
评论
1 楼 漂泊一剑客 2014-12-29  
为博主点赞

相关推荐

    数据结构经典问题和算法分析

    例如,对于n个元素的排序问题,当n=1时,不需任何计算;n=2时,只要作一次比较即可排好序;n=3时只要作3次比较即可,…。而当n较大时,问题就不那么容易处理了。要想直接解决一个规模较大的问题,有时是相当困难的。...

    C语言经典算法大全

    C语言经典算法大全 老掉牙 河内塔 费式数列 巴斯卡三角形 三色棋 老鼠走迷官(一) 老鼠走迷官(二) 骑士走棋盘 八个皇后 八枚银币 生命游戏 字串核对 双色、三色河内塔 背包问题(Knapsack Problem...

    C语言经典算法大全(几十个经典案例,都有详尽代码)

    C语言经典几十个经典案例,都有详尽 河内塔 费式数列 巴斯卡三角形 三色棋 老鼠走迷官(一) 老鼠走迷官(二) 骑士走棋盘 八个皇后 八枚银币 生命游戏 字串核对 双色、三色河内塔 背包问题(Knapsack ...

    c++递归/递推经典题目

    这里是本蒟蒻整理/写的递归...包含:过河卒、过河卒升级版、汉诺塔、级数求和、勒让德多项式、流感传染、判断回文、判断元素是否存在、平方根级数、平面分割升级版、全排列递归版、位数问题、字符串倒序输出、走楼梯。

    经典项目.zip

    搜索算法:搜索算法用于在数据集中查找特定元素的算法。常见的搜索算法包括线性搜索、二分搜索等。 图算法:图算法用于处理图结构的数据,如最短路径算法(如Dijkstra算法、Floyd-Warshall算法)、最小生成树算法...

    c语言经典算法包括老掉牙,汉诺塔,三色旗

    m元素集合的n个元素子集 数字拆解 排序 得分排行 选择、插入、气泡排序 Shell 排序法 - 改良的插入排序 Shaker 排序法 - 改良的气泡排序 Heap 排序法 - 改良的选择排序 快速排序法(一) 快速排序法(二) ...

    经典常用算法 河内塔

    m元素集合的n个元素子集 数字拆解 排序 得分排行 选择、插入、气泡排序 Shell 排序法 - 改良的插入排序 Shaker 排序法 - 改良的气泡排序 Heap 排序法 - 改良的选择排序 快速排序法(一) 快速排序法(二...

    经典算法教程 举例详解

    经典算法.pdf 算法举例详解 河内塔 费式数列 巴斯卡三角形 三色棋 老鼠走迷官(一) 老鼠走迷官(二) 骑士走棋盘 八个皇后 八枚银币 生命游戏 字串核对 双色、三色河内塔 背包问题(Knapsack Problem) 数、运算 ...

    经典算法大全,常用的算法都在这里

    m元素集合的n个元素子集 数字拆解 排序 得分排行 选择、插入、气泡排序 Shell 排序法 - 改良的插入排序 Shaker 排序法 - 改良的气泡排序 Heap 排序法 - 改良的选择排序 快速排序法(一) 快速排序法(二...

    C语言入门经典(第4版)--源代码及课后练习答案

    3.2 多项选择问题 103 3.2.1 给多项选择使用else-if语句 104 3.2.2 switch语句 104 3.2.3 goto语句 113 3.3 按位运算符 114 3.3.1 按位运算符的op=用法 116 3.3.2 使用按位运算符 117 3.4 设计程序 120 ...

    经典算法(c&java版)

    • m元素集合的n个元素子集 • 数字拆解 排序 • 得分排行 • 选择、插入、气泡排序 • Shell 排序法 - 改良的插入排序 • Shaker 排序法 - 改良的气泡排序 • Heap 排序法 - 改良的选择排序 • 快速排序法...

    经典Java23种设计模式.rar

    可应用于多种不同场合,所以解决方案并不描述一个特定而具体的设计或实现,而是提供设计问题的抽象描述和怎样用一个具有一般意义的元素组合(类或对象组合)来解决这个问题。 (4)效果(consequences) 描述了模式应用...

    经典的C程序220案列

    046 选择排序 047 堆排序 048 归并排序 049 基数排序 050 二叉搜索树操作 051 二项式系数递归 052 背包问题 053 顺序表插入和删除 054 链表操作(1) 055 链表操作(2) 056 单链表就地逆置 057 运动会...

    经典算法全部用C语言实现

    m元素集合的n个元素子集 数字拆解 排序 得分排行 选择、插入、气泡排序 Shell 排序法 - 改良的插入排序 Shaker 排序法 - 改良的气泡排序 Heap 排序法 - 改良的选择排序 快速排序法(一) 快速排序法(二) ...

    C语言 经典算法 算法大全

    C语言经典算法,包括1.汉若塔 2 2.费式数列 3 3. 巴斯卡三角形 4 4.三色棋 5 5.老鼠走迷官(一) 7 6.老鼠走迷官(二) 9 7.骑士走棋盘 10 8.八皇后 13 9.八枚银币 15 10.生命游戏 17 11.字串核对 20 12.双色、三色...

    经典算法(C语言)包含51个经典算法的C语言实现

    30.m元素集合的n个元素子集 66 31.数字拆解 68 32.得分排行 71 33.选择、插入、气泡排序 73 34.Shell 排序法 - 改良的插入排序 77 35.Shaker 排序法 - 改良的气泡排序 80 36.排序法 - 改良的选择排序 82 37.快速排序...

    Java和C语言实现各种经典算法(含代码图例)

    Java和C语言实现各种经典算法(含代码图例) 老掉牙 河内塔 费式数列 巴斯卡三角形 三色棋 老鼠走迷官(一) 老鼠走迷官(二) 骑士走棋盘 八个皇后 八枚银币 生命游戏 字串核对 双色、三色河内塔 背包...

    c语言经典算法

    m元素集合的n个元素子集 数字拆解 排序 得分排行 选择、插入、气泡排序 Shell 排序法 - 改良的插入排序 Shaker 排序法 - 改良的气泡排序 Heap 排序法 - 改良的选择排序 快速排序法(一) 快速排序法(二) ...

Global site tag (gtag.js) - Google Analytics