剑指 Offer 40. 最小的k个数
输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
题解;
比较直观的想法是使用堆数据结构来辅助得到最小的 k 个数。堆的性质是每次可以找出最大或最小的元素。我们可以使用一个大小为 k 的最大堆(大顶堆),将数组中的元素依次入堆,当堆的大小超过 k 时,便将多出的元素从堆顶弹出。
。
class Solution:
def getLeastNumbers(self, arr: List[int], k: int) -> List[int]:
#求前k个最小用最大堆,求前k个最大用最小堆
n=len(arr)
def maxheap(a,i,length):
l=2*i+1
r=2*i+2
large=i
if l<length and a[l]>a[large]:
large=l
if r<length and a[r]>a[large]:
large=r
if large!=i:
#当父节点值和最大值索引不相同是时,需要将最大值交换到父节点上
a[large],a[i]=a[i],a[large]
#由于第大元素的索引被置换到该处,故仍然需要吊用递归来对该出索引的元素进行放置
maxheap(a,large,length)
#由堆排序的性质可得,对于一个数组a,最后一个节点为n-1,则其父节点为n//2,从倒数第n-1个节点开始,遍历的都是根节点。
def buildheap(a,length):
for i in range(n//2,-1,-1):
maxheap(a,i,length)
#如果采用只维护数组的前k个,需要对数组进行判断,否则报错。
if not arr or k <= 0:
return []
if len(arr) <= k:
return arr
heap = arr[:k]
buildheap(heap,k) # 构建大根堆
for i in range(k, len(arr)):
if arr[i] < heap[0]: # 当前元素比堆根小,则弹出堆根并插入当前元素
heap[0] = arr[i]
maxheap(heap, 0,k) # 重新调整堆根
return heap