Python技术迷

找出无序数组中第 K 个最小元素

说实话,这类题目虽然常见,但你要是直接在面试里就甩出 heapq.nsmallest(),面试官八成会说一句:“你就记住了个库函数?”我不是说不能用,而是你得知道为啥这么用,背后的逻辑得讲得出来。否则,人家凭啥信你真的理解了?

咱们来认真聊一下这个问题,顺带看看有哪些更合适的方式,顺便讲清楚底层发生了啥。

找第 K 小的数,真就排序完取第 K 个?

先别急着写代码,咱们先想一想:假如你有一个数组 [3, 2, 1, 5, 6, 4],要找第 2 小的数,是不是排序之后变成 [1, 2, 3, 4, 5, 6],然后返回下标为 1 的元素,也就是 2?

这当然可以,但时间复杂度是 O(n log n),其实这个问题没必要排完整个序。

面试官的潜台词往往是:你能不能只排你要的部分?

Python 的 heapq.nsmallest() 是怎么做的?

import heapq

defkth_smallest(nums, k):
return heapq.nsmallest(k, nums)[-1]

这个代码看着简单,它干的事其实是:用一个最大堆(在 nsmallest 的实现里),维护前 k 小的元素,最后返回第 k 个。这样做的时间复杂度是 O(n log k),比起直接排序 O(n log n) 要划算多了,尤其是当 k 很小的时候。

那你要是真想自己写一个,是不是还能用堆?

当然可以!我们可以手动维护一个最大堆(注意:Python 的 heapq 默认是最小堆,所以要反着存)。

来,给个更硬核一点的写法:

import heapq

defkth_smallest(nums, k):
    max_heap = [-num for num in nums[:k]]
    heapq.heapify(max_heap)
for num in nums[k:]:
if -num > max_heap[0]:  # 因为我们是负数,-num > max_heap[0] 就是 num < -max_heap[0]
            heapq.heappop(max_heap)
            heapq.heappush(max_heap, -num)
return -max_heap[0]

这个写法的好处是你可以跟面试官解释你怎么一步步“手撸了个堆”,显得你真的理解算法。

那有没有更暴力但面试官喜欢的方案?

有,就是 快速选择 QuickSelect。这是快速排序的变种,平均时间复杂度是 O(n)。

import random

defquickselect(nums, k):
ifnot nums:
returnNone
    pivot = random.choice(nums)
    lows = [el for el in nums if el < pivot]
    highs = [el for el in nums if el > pivot]
    pivots = [el for el in nums if el == pivot]

if k <= len(lows):
return quickselect(lows, k)
elif k > len(lows) + len(pivots):
return quickselect(highs, k - len(lows) - len(pivots))
else:
return pivots[0]

这个方法没用额外的数据结构,纯靠递归来 partition,够原始,也够优雅。拿出去说也是加分项。

那你问我面试怎么回答?

如果是我被问到这个题,我会这么说:

最优回答:

这个问题我会根据实际需求选择不同的解法:

如果是一次性操作,数据量不大,我可以直接用 heapq.nsmallest() 拿出前 K 小的值,取最后一个,代码简单直观,时间复杂度是 O(n log k)。

但如果我想优化性能,尤其是在大数据场景下,我会考虑用快速选择算法 QuickSelect,它的平均时间复杂度是 O(n)。这个方法基于快速排序的分区思想,通过随机选择 pivot 来不断缩小搜索范围,直到找到第 K 小的值。

如果数据是动态的,比如数据流中持续加入元素,我可能会维护一个大小为 K 的最大堆,这样每次插入后都能快速判断当前第 K 小的值,这个思路也适用于找第 K 大的元素,只是堆的大小和排序规则要调一下。

所以总结来说,暴力法能做,堆是实用方案,QuickSelect 是性能优选,视场景选择。

你看,这种回答既体现了技术深度,也展示了你的实际思考能力。如果你只会一个库函数,可能就差那么一丢丢了。

最后,我为大家打造了一份deepseek的入门到精通教程,完全免费:https://www.songshuhezi.com/deepseek

也可以看我写的这篇文章《DeepSeek满血复活,直接起飞!》来进行本地搭建。

对编程、职场感兴趣的同学,大家可以联系我微信:golang404,拉你进入“程序员交流群”。
🔥虎哥私藏精品 热门推荐🔥

虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》。

资料包含了《IDEA视频教程》、《最全python面试题库》、《最全项目实战源码及视频》及《毕业设计系统源码》,总量高达650GB,全部免费领取