topK问题

 topK问题:N个数,前K大的数(k<n)

1.排序后切片O(nlogn)+k

2.冒排,插排,选择排序  KN

3.堆排序  :O(nlogK)取列表前K个元素建立1个小根堆,堆顶就是目前前K大的数

 

def sift(li,low,high):
    """
    :param li: 列表
    :param low: 堆的根节点位子
    :param high: 堆的最后一个元素的位置
    :return:
    """
    i = low     #i最开始指向根节点
    j = 2*i +1   #j开始是左孩子
    tmp = li[i]  #把堆顶存起来
    while j<=high:  #只要j位置有数
        if j+1<=high and li[j+1]<li[j]: #如果右孩子有并且比较大
            j = j+1  #j指向右孩子
        if li[j]<tmp:
            li[i]=li[j]
            i = j  #往下看一层
            j = 2*i+1  #通过父亲找下下层的孩子
        else:    #tmp更大,把tmp放到i的位置上
            li[i] = tmp   #把tmp放到某一级领导的位置上
            break
    else:
        li[i] =tmp  #把tmp放到叶子节点上

def topk(li,k):
    heap = li[0:k]
    #1.建堆
    for i in range((k-2)//2,-1,-1):
        sift(heap,i,k-1)
    #2.遍历
    for i in range(k,len(li)-1):
        if li[i]>heap[0]:
            heap[0]=li[i]
            sift(heap,0,k-1)
    #3.出数
    for i in range(k-1,-1,-1):
        heap[0],heap[i]=heap[i],heap[0]
        sift(heap,0,i-1)

    return heap
import random
li = list(range(1000))
random.shuffle(li)
print(topk(li,5))

执行结果:

 

posted @ 2019-07-08 01:52  小萍瓶盖儿  阅读(99)  评论(0编辑  收藏  举报