1. 问题背景与核心概念
在算法面试和日常编程中,"215.数组中的第K个最大元素"是一个经典问题。这个问题看似简单,但背后涉及多种算法思想和优化技巧。我第一次遇到这个问题是在准备技术面试时,当时觉得直接排序再取第K个元素不就行了?但深入思考后发现事情没那么简单。
这个问题的标准描述是:给定一个整数数组nums和整数k,请返回数组中第k个最大的元素。注意是排序后的第k个最大元素,而不是第k个不同的元素。例如,数组[3,2,1,5,6,4]中第2个最大的元素是5,因为排序后是[6,5,4,3,2,1]。
注意区分"第K个最大"和"第K大"的概念,在实际面试中,有些面试官会故意混淆这两个表述来考察你的理解能力。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 基础解法与复杂度分析
2.1 直接排序法
最直观的解法是对数组进行排序,然后直接取第k个元素。在Python中,这只需要一行代码:
python复制def findKthLargest(nums, k):
return sorted(nums, reverse=True)[k-1]
这种方法的时间复杂度是O(nlogn),主要来自排序操作。空间复杂度取决于排序算法的实现,Python的sorted()使用Timsort算法,空间复杂度为O(n)。
虽然这种方法简单直接,但在面试中仅仅给出这个解法通常不会让面试官满意。他们期望你能提出更优的解决方案。
2.2 部分排序优化
考虑到我们只需要第k个最大元素,不需要完整的排序,可以使用部分排序算法。Python的heapq模块提供了nlargest函数:
python复制import heapq
def findKthLargest(nums, k):
return heapq.nlargest(k, nums)[-1]
这种方法的时间复杂度是O(nlogk),因为构建和维护大小为k的堆需要logk的时间,共n个元素。空间复杂度是O(k)用于存储堆。
3. 进阶解法:快速选择算法
3.1 算法原理
快速选择(Quickselect)算法是解决这个问题的黄金标准,它基于快速排序的分区思想,平均时间复杂度可以达到O(n),最坏情况下为O(n²)。
算法步骤如下:
- 随机选择一个pivot元素
- 将数组分为两部分:大于pivot的和小于等于pivot的
- 如果pivot正好是第k-1个元素,则返回它
- 否则根据情况在左半部分或右半部分递归查找
3.2 Python实现
python复制import random
def findKthLargest(nums, k):
def quickselect(left, right, k_smallest):
if left == right:
return nums[left]
pivot_index = random.randint(left, right)
pivot_index = partition(left, right, pivot_index)
if k_smallest == pivot_index:
return nums[k_smallest]
elif k_smallest < pivot_index:
return quickselect
