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)
    这个逻辑比较简单,就不写代码了。

  • 相关阅读:
    hihoCoder#1037 : 数字三角形(DP)
    Android安全机制
    Java五道输出易错题解析(进来挑战下)
    【Mail】JavaMail介绍及发送邮件(一)
    【Mail】搭建邮件服务器(LAMP+Postfix+Dovcot+PostfixAdmin+Roundcubemail)
    【Mail】telnet收发邮件过程
    【Mail】邮件的基础知识和原理
    【Java】JavaWeb权限管理
    【Java】JDBC连接数据库
    【Mysql】权限管理
  • 原文地址:https://www.cnblogs.com/wickedpriest/p/14256780.html
Copyright © 2011-2022 走看看