📅  最后修改于: 2023-12-03 15:26:08.958000             🧑  作者: Mango
堆是一种数据结构,用于维护一个元素集合,并支持插入、删除最小/最大元素、以及查找最小/最大元素等操作。堆通常以树的形式实现,可以是最小堆或最大堆。
问题 3 是一个与堆数据结构有关的问题:给定一个长度为n的整数数组nums和一个整数k,找出数组nums中前k个最大的元素。本问题的解法涉及到堆的应用。
这是一种比较简单的方法:维护一个大小为k的最小堆,遍历数组nums中的每个元素,如果当前元素比堆中最小元素还大,那么就把堆中最小的元素出堆,并将当前元素加入堆中。最终堆中的元素就是前k个最大的元素。
import heapq
def find_top_k(nums, k):
heap = []
for num in nums:
if len(heap) < k:
heapq.heappush(heap, num)
elif num > heap[0]:
heapq.heappop(heap)
heapq.heappush(heap, num)
return heap
这种方法的时间复杂度是 $\mathcal{O}(n \log k)$,空间复杂度是 $\mathcal{O}(k)$。注意,如果需要输出前k个最大的元素,可以将堆中的元素逆序输出。
也可以用快速排序的思想解决本问题。快速排序分区时,每次可以确定一个元素在排序后的位置。那么如果当前确定的位置在前k个位置之后,就只需要对左半部分继续排序即可。
def find_top_k(nums, k):
def quick_select(left, right):
if left == right:
return
pivot = nums[left]
i, j = left, right
while i < j:
while i < j and nums[j] <= pivot:
j -= 1
nums[i] = nums[j]
while i < j and nums[i] >= pivot:
i += 1
nums[j] = nums[i]
nums[i] = pivot
if i == k - 1:
return
elif i > k - 1:
quick_select(left, i - 1)
else:
quick_select(i + 1, right)
quick_select(0, len(nums) - 1)
return sorted(nums[:k], reverse=True)
快速排序的时间复杂度是 $\mathcal{O}(n \log n)$,空间复杂度是 $\mathcal{O}(1)$。但是,如果数组中有大量相等的元素,快速排序的性能将下降。在这种情况下,可以考虑使用基数排序或桶排序等排序算法。