现在有n个数,设计算法得到前k大的数 k<n
1.解决思路:
1.排序后切片 O(nlogn)
2.lowB三人组排序 O(mn)
3.堆排序 O(mlogn)
2.堆排序解决topK问题
1.取列表前K个元素建立一个小根堆,堆顶就是目前就是第K大的数
2.依次向后遍历原列表,对于列表中的元素,如果小于堆顶则忽略该元素,如果大于堆顶则将该元素与堆顶元素交换位置,并且对堆进行一次调整
3.遍历列表所有元素后倒序弹出堆顶
def sift_small(li, low, high): # 小根堆
"""
:param li: 所要排序的列表
:param low: 树的根节点
:param high: 树的深度
:return:
"""
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:
break
else:
li[i] = tmp
def top_k(li, k):
heap = li[0:k]
# 1.创建堆
for i in range((k - 2) // 2, -1, -1): # 获取heap列表叶子节点的父节点
sift_small(heap, i, k-1) # 构建小根堆
# 2.遍历堆
for i in range(k, len(li)-1): # 获取li列表从k之后的所有值
if li[i] > heap[0]: # 如果heap根节点小于列表中下标i的值
heap[0] = li[i] # 将根节点与列表中下标i的值位置替换
sift_small(heap, 0, k-1) # 取列表中元素前n大的数开始构建小根堆
for i in range(k-1, -1, -1): # 遍历小根堆使其按照从大到小排序
heap[0], heap[i] = heap[i], heap[0] # 置换根节点与叶子节点
sift_small(heap, 0, i - 1) # 每次将树更新一遍并且叶子节点减少一个
return heap
List = [i for i in range(100)]
random.shuffle(List)
print(List)
print(top_k(List, 5))