https://leetcode-cn.com/problems/zui-xiao-de-kge-shu-lcof/solution/pythonti-jie-sort-ji-yu-kuai-su-pai-xu-da-gen-dui-/
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。
如果是查找第k个数字,第一次划分之后,划分的位置如果大于k,那么就在前面的子数组中进行继续划分,反之则在后面的子数组继续划分,时间复杂度O(n)
该方法基于二叉树或者堆来实现,首先把数组前k个数字构建一个最大堆,然后从第k+1个数字开始遍历数组,如果遍历到的元素小于堆顶的数字,那么就将换两个数字,重新构造堆,继续遍历,最后剩下的堆就是最小的k个数,时间复杂度O(nlog k)。
# -*- coding:utf-8 -*-
class Solution:
def GetLeastNumbers_Solution(self, tinput, k):
if k > len(tinput) or k <= 0:
return []
'''堆化'''
def heapify(a, i):
left = 2*i + 1
right = 2*i + 2
largest = i
if left < len(a) and a[left] > a[largest]:
largest = left
if right < len(a) and a[right] > a[largest]:
largest = right
if largest != i:
a[largest], a[i] = a[i], a[largest]
heapify(a, largest) # 递归:看孩子的孩子节点
'''建堆'''
def buildMaxHeap(a):
# import math
# for i in range(math.floor(len(a)/2), -1, -1): # 牛客编译报错 range() integer start argument expected, got float.
for i in range(len(a)//2, -1, -1):
heapify(a, i)
return a # 必须加
# 建立大小为k的大顶堆,索引从0到k-1
heap = buildMaxHeap(tinput[:k])
# 从下标k处遍历
for num in tinput[k:]:
if num < heap[0]:
heap[0] = num
heapify(heap, 0)
ans = []
while k > 0 and len(heap) != 0:
ans.append(heap[0])
heap[0] = heap[-1]
heap.pop() # 删除队尾
heapify(heap, 0)
k -= 1
return ans[::-1]
# -*- coding:utf-8 -*-
class Solution:
def GetLeastNumbers_Solution(self, tinput, k):
import heapq
if tinput == None or len(tinput) < k or len(tinput) <= 0 or k <= 0:
return []
# if len(tinput) == k:
# return tinput
output = [] # 存放大顶堆的容器
for i in tinput:
if len(output) < k:
output.append(i)
else:
output = heapq.nlargest(k, output) # 重构建大顶堆:返回前 k 个最大元素组成的列表
if i >= output[0]:
continue # 如果下个数大于“堆中最大数”,跳过;反之则替换“堆中最大数”
else:
output[0] = i
output = heapq.nlargest(k, output) # 处理边界条件,k = len(tinput)
return output[::-1]
tinput = [4,5,1,6,2,7,3,8]
s = Solution()
print(s.GetLeastNumbers_Solution(tinput, 4))
print(s.GetLeastNumbers_Solution(tinput, 5))
print(s.GetLeastNumbers_Solution(tinput, 7))
print(s.GetLeastNumbers_Solution(tinput, 8)) # 边界条件