K个最大(最小)元素的算法

问题描述:给定具有N个元素的全序集合A,比较算符为<=,求最大的K<=N个元素,不要求排序。下面按照取K个最小值的情况讨论。
基本思想:类似于快速排序法,选择一个元素将其插入到数组的一个位置,使得左侧的元素都小于等于该标记元素,右侧元素都大于等于该元素。

  • 取第一个元素为标记元素,扫描后续的元素,并与其比较,分为三类
    • 一类是全部小于该元素,数组计为A_1,个数计为N_1
    • 一类是全部等于该元素,数组计为A_2,个数计为N_2
    • 一类是全部大于该元素,数组计为A_3,个数计为N_3
    • 定义M_1=N_1, M_2 = N_1+N_2, M_3 = N_1 + N_2 + N_3
  • KM_1,M_2,M_3比较,确定其位置。
  • K=M_1时,返回结果即A_1
  • K=M_2时,返回结果即A_1\cup A_2
  • K=M_3时,返回结果即A集合本身
  • K < M_1时,对A_1集合递归调用上述过程
  • M_1 < K < M_2时,在A_2集合中递归调用上述过程找到A_2集合中的前K-M_1个元素B,返回A_1\cup B
  • M_2 < K < M_3时,在A_3集合中递归调用上述过程,找到A_3集合中的前K-M_2个元素C,返回A_1\cup A_2\cup C

参考Haskell代码:

ksplit 0 xs = ([], xs)
ksplit k xs
    = let x = head xs
          xs1 = filter (<  x) xs
          xs2 = filter (== x) xs
          xs3 = filter (>  x) xs
          n1  = length xs1
          n2  = length xs2 + n1
          n3  = length xs3 + n2
      in  if k > length xs
          then error "not_enough_elements"
          else if k == n1
               then (xs1, xs2 ++ xs3)
               else if k == n2
                    then (xs1 ++ xs2, xs3)
                    else if k == n3
                         then (xs, [])
                         else if k < n1
                              then let (ys1, ys2) = ksplit k xs1
                                   in  (ys1, ys2 ++ xs2 ++ xs3)
                              else if k < n2 -- k \in (n1, n2)
                                   then (xs1 ++ take (k - n1) xs2, take (n2 - k) xs2 ++ xs3)
                                   else let (ys1, ys2) = ksplit (k - n2) xs3 -- k \in (n2, n3)
                                        in  (xs1 ++ xs2 ++ ys1, ys2)


©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 一、基础知识:1、JVM、JRE和JDK的区别:JVM(Java Virtual Machine):java虚拟机...
    杀小贼阅读 2,575评论 0 4
  • 1)这本书为什么值得看: Python语言描述,如果学的Python用这本书学数据结构更合适 2016年出版,内容...
    孙怀阔阅读 12,940评论 0 15
  • 官网 中文版本 好的网站 Content-type: text/htmlBASH Section: User ...
    不排版阅读 4,727评论 0 5
  • 这是16年5月份编辑的一份比较杂乱适合自己观看的学习记录文档,今天18年5月份再次想写文章,发现简书还为我保存起的...
    Jenaral阅读 3,172评论 2 9
  • 早上5:30起床,一大堆的事情等着去做,全天有一半的任务要在早上完成,家务有做早饭,准备午饭,打扫卫生,洗衣服;自...
    洛阳向日葵阅读 213评论 0 0

友情链接更多精彩内容