📅  最后修改于: 2023-12-03 15:42:18.731000             🧑  作者: Mango
这道题要求我们找一个长度为 n 的数组中最小的 k 个数。首先,我们可以先将数组排序,然后取前 k 个数即可。时间复杂度为 $O(n \log n)$,空间复杂度为 $O(1)$。
def find_min_k_numbers(arr, k):
arr.sort()
return arr[:k]
当然,我们也可以利用堆来解决这个问题。我们可以维护一个大小为 k 的最大堆,遍历数组,每当遍历到的数小于堆顶的数时,就将堆顶元素弹出,将遍历到的数加入堆中。最后,堆中剩余的元素即为最小的 k 个数。时间复杂度为 $O(n \log k)$,空间复杂度为 $O(k)$。
import heapq
def find_min_k_numbers(arr, k):
heap = []
for num in arr:
if len(heap) < k:
heapq.heappush(heap, -num)
elif -num > heap[0]:
heapq.heappop(heap)
heapq.heappush(heap, -num)
return [-x for x in heap]
同样,我们也可以使用快速排序的 partition 操作来找到最小的 k 个数。首先选取一个数作为 pivot,将数组划分成两部分,小于等于 pivot 的放在左边,大于 pivot 的放在右边。若左半边的元素个数不足 k,那么说明最小的 k 个数都在左半边,此时递归对左半边进行 partition 操作。否则,说明最小的 k 个数要么全部在左半边,要么部分在左半边,此时递归对左半边进行 partition 操作。时间复杂度为 $O(n)$,但递归的栈空间复杂度可能很高。
def partition(arr, l, r):
pivot = arr[r]
i = l - 1
for j in range(l, r):
if arr[j] <= pivot:
i += 1
arr[i], arr[j] = arr[j], arr[i]
arr[i + 1], arr[r] = arr[r], arr[i + 1]
return i + 1
def find_min_k_numbers(arr, k):
def quick_select(arr, l, r, k):
if l >= r:
return arr[:k]
pivot_index = partition(arr, l, r)
if pivot_index > k - 1:
return quick_select(arr, l, pivot_index - 1, k)
else:
return quick_select(arr, pivot_index + 1, r, k)
return quick_select(arr, 0, len(arr) - 1, k)
综上所述,我们可以选择以上三种方法来求最小的 k 个数。具体选择哪一种方法,可以根据数据规模、时间复杂度和空间复杂度等综合考虑。