zoukankan      html  css  js  c++  java
  • 第K小的数

    给出一个数组,从中找到第K小的数,这可以算是一个经典的算法题了。今天在这里给出几种解法:
    1.最简单的方法,就是对数组进行排序,然后选取其中前K个数即可。排序算法一般我们可以用快速排序,这样的话时间复杂度就是O(NlgN)。但是以上这种方法还是显得有些慢,那有没有比它更快的方法呢?
    2.参考快速排序,快排在递归的过程中,需要不断将数组分为两部分,且一部分总是小于另外一部分,我们可以用这种方法对数组进行递归,直到分出前K个元素作为几个集合为止。代码如下:

    def partition(numbers, begin, end):
        assert begin <= end
        if begin == end:
            return begin
        mid = numbers[begin]
        index = begin + 1
        for i in xrange(begin+1, end+1):
            if numbers[i] > mid:
                continue
            else:
                tmp = numbers[i]
                numbers[i] = numbers[index]
                numbers[index] = tmp
                index += 1
        tmp = numbers[index-1]
        numbers[index-1] = mid
        numbers[begin] = tmp
        return index-1
        
    def getLeastKnumber(numbers, k):
        l = len(numbers)
        begin = 0
        end = l-1
        index = partition(numbers, begin, end)
        while index != k-1:
            if index < k-1:
                begin = index + 1
            else:
                end = index - 1
            index = partition(numbers, begin, end)
        return numbers[index]
    

    该方法的时间复杂度为O(N)。
    3.以上的两个方法都需要对所有数据遍历多次,如果数据量太大,都没办法全部装进内存了,此时也就没法对数组排序,那么此时该怎么做呢?
    我们可以先拿出前K个元素建一个最大堆,堆顶元素是其中最大的数。然后遍历数组其他元素,与堆顶的元素进行比较。
    有这么几种情况:
    遍历的数>=堆顶元素,那么可以跳过,因为我们要寻找第K小的数,遍历的数比K个数中最大那个都要大,那它肯定不是第K小的数(有K个数都要比它小呢)。
    遍历的数<堆顶元素,那么这个数和堆顶元素互换,并重新维护堆。
    一直到遍历结束,取出堆顶的数就是第K小的数了。
    该算法的时间复杂度为O(NlgK)
    这个逻辑比较简单,就不写代码了。

  • 相关阅读:
    emqttd的启动脚本
    vue2的全局变量
    windows 上优雅的安装 node 和 npm
    Intent数据清理
    android 滑动刷新的实验总结
    Android 音量键拦截
    多进程通讯笔记 android aidl
    perl-Thread-Queue for openwrt
    openwrt的编译环境
    高德地图白屏的问题
  • 原文地址:https://www.cnblogs.com/wickedpriest/p/14256780.html
Copyright © 2011-2022 走看看