题目

在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

示例 1:
输入: [3,2,1,5,6,4]k = 2
输出: 5

示例 2:
输入: [3,2,3,1,2,4,5,5,6]k = 4
输出: 4

说明:
你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。

方案一(堆)

  1. class Solution:
  2. def findKthLargest(self, nums: List[int], k: int) -> int:
  3. heap = nums[:k]
  4. heapq.heapify(heap)
  5. for i in range(k, len(nums)):
  6. if nums[i] > heap[0]: # 比堆中最小元素大
  7. heapq.heapreplace(heap, nums[i])
  8. return heap[0]

  1. class Solution:
  2. def findKthLargest(self, nums: List[int], k: int) -> int:
  3. return heapq.nlargest(k, nums)[-1]

方案二(分治)

  1. class Solution:
  2. def findKthLargest(self, nums: List[int], k: int) -> int:
  3. # 快排思想+问题转化:第 k 个最大元素也就是第 N - k 个最小元素
  4. def partition(left, right, pivot_index):
  5. pivot = nums[pivot_index]
  6. # 将 pivot 移到最后
  7. nums[right], nums[pivot_index] = nums[pivot_index], nums[right]
  8. # 将小于 pivot 的移动在前面
  9. store_index = left
  10. for i in range(left, right):
  11. if nums[i] < pivot:
  12. nums[i], nums[store_index] = nums[store_index], nums[i]
  13. store_index += 1
  14. # 最后一个节点为分界点
  15. nums[right], nums[store_index] = nums[store_index], nums[right]
  16. # 返回分区点
  17. return store_index
  18. def select(left, right, k_smallest):
  19. if left == right:
  20. return nums[left]
  21. pivot_index = random.randint(left, right)
  22. pivot_index = partition(left, right, pivot_index)
  23. if k_smallest == pivot_index:
  24. return nums[pivot_index]
  25. elif k_smallest < pivot_index:
  26. return select(left, pivot_index - 1, k_smallest)
  27. else:
  28. return select(pivot_index + 1, right, k_smallest)
  29. return select(0, len(nums) - 1, len(nums) - k)