问题:现在有n个数,设计算法得到前k大的数。(k<n)
解决思路:
1. 排序后切片 O(nlog n)
2. 排序LowB三人组 O(kn)
3. 堆排序思路 O(nlog k)
堆排序解决:
1. 取列表前k个元素建立一个小根堆,堆顶就是目前第k大的数
2. 依次向后遍历原列表,对于列表中的元素,如果小于堆顶,则忽略该元素;
如果大于 堆顶,则将堆顶更换为该元素,并且对堆顶进行一次堆调整;
3. 遍历列表所有元素后,倒序弹出堆顶
def small_sift(li,low,high):
i = low
j = 2*i + 1
tmp = li[low]
while j <= high:
if j + 1 <= high and li[j+1] < li[j]:
j = j + 1
if li[j] < tmp:
li[i] = li[j]
i = j
j = 2*i + 1
else:
li[i] = tmp
break
else:
li[i] = tmp
def topk(li,k):
heap = li[0:k]
for i in range((k-2)//2,-1,-1):
small_sift(heap,i,k-1)
for i in range(k,len(li)-1):
if li[i] > heap[0]:
heap[0] = li[i]
small_sift(heap,0,k-1)
for i in range(k-1,-1,-1):
heap[0],heap[i] = heap[i],heap[0]
small_sift(heap,0,i-1)
return heap
import random
li = list(range(100))
random.shuffle(li)
print(topk(li, 10))
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/6cd5e0e71ff54b1581c88bf4644e9721.png)