欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

topK问题

程序员文章站 2022-03-24 17:35:38
...

概述

在N个乱序数字中查找第K大的数字,时间复杂度可以减小至O(N).
可能存在的限制条件:
要求时间和空间消耗最小、海量数据、待排序的数据可能是浮点型等。

方法

方法一

  • 对所有元素进行排序,之后取出前K个元素,时间复杂度高,不提倡。 *
    思路:使用快排,选择排序,堆排序。
    时间复杂度:排序复杂度nlogn,最后要访问第K个元素,因此是O(n*logn)+O(K)=O(n*logn)
    特点:需要对全部元素进行排序,K=1时,时间复杂度也为O(n*logn)。

方法二

  • 只需要对前K个元素排序,剩下N-K个元素不需要排序,时间复杂度高,不提倡。 *
    思路:使用选择排序 或 冒泡排序, 进行K此选择,可得到第K大的数。
    时间复杂度:每一次大循环遍历复杂度是n,共遍历K次,因此是O(n*k)
def selectionSort(arr, k):
    length = len(arr)
    minIndex = 0
    for i in range(length):
        minIndex = i
        for j in range(i+1,length):
            if arr[j] < arr[minIndex]:
                minIndex = j

        arr[i], arr[minIndex] = arr[minIndex], arr[i]
        if i == k:
            return arr[:k]

    return arr

arr = [3,4,9,2,1,0,-10]
print(selectionSort(arr, 3))

方法三

  • 不对前K个数排序+不对N-K个数排序 *
    思路:寻找第K个大元素
    具体方法:使用类似快排,执行一次快排后,每次只选择一部分继续执行快排,直到找到第K个大元素为止,此时这个元素在数组位置后面的元素即所求。
    时间复杂度:
  • 若随机选取枢纽,线性期望时间O(N)
  • 若选取数组的“中位数的中位数”作为枢纽,最坏情况下的时间复杂度O(N)
    利用快排的思想,从数组S中随机找出一个元素X,把数组分为两部分Sa和Sb。Sa中的元素大于等于X,Sb中元素小于X。这时有两种情况:
  1. Sa中元素的个数小于k,则Sb中的第k-|Sa|个元素即为第k大数;
  2. Sa中元素的个数大于等于k,则返回Sa中的第k大数。
    利用快排的partion思想T(n) = 2T(n/2) + O(1) 时间复杂度为O(n)
    该方法只有当我们可以修改输入的数组时可用,位于数组左边的k个数字就是最小的k个数字(但这k个数字不一定是排序的),位于第k个数右边的数字都比第k个数字大。

上一篇: 并查集(总结)

下一篇: TopK问题