1. 问题重述与理解
LeetCode 1984题"学生分数的最小差值"要求我们从一个学生分数数组中,选取任意k个学生的分数,使得这k个分数中最高分和最低分的差值最小。换句话说,我们需要找到所有可能的k个学生组合中,分数极差最小的那个组合对应的极差值。
这个问题可以形象地理解为:在一群学生中挑选一个小团队,使得这个小团队内部的成绩分布尽可能均匀,避免出现成绩差距过大的情况。这在教育场景中很有实际意义,比如需要选拔成绩相近的学生参加某个竞赛或活动。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 解题思路分析
2.1 暴力解法与优化空间
最直观的解法是枚举所有可能的k个学生组合,计算每个组合的极差,然后取最小值。这种方法的时间复杂度是C(n,k),当n和k较大时(比如n=1000,k=500),计算量会变得非常大,显然不可行。
2.2 排序的妙用
观察题目特点,我们发现如果将数组排序,那么最小差值一定出现在某个连续的k个元素窗口中。这是因为:
- 排序后,数组是有序的,相邻元素的差值更小
- 要获得最小差值,应该选择数值上接近的元素
- 连续窗口内的极差计算简单(只需用窗口最后一个元素减去第一个元素)
这种思路类似于滑动窗口算法,我们只需要维护一个大小为k的窗口,滑动这个窗口遍历整个排序后的数组,记录遇到的最小极差即可。
3. 算法实现详解
3.1 排序预处理
首先对数组进行排序。排序的时间复杂度取决于使用的算法:
- 快速排序平均O(n log n)
- 归并排序稳定O(n log n)
- 对于小规模数据,插入排序可能更高效
在大多数编程语言的标准库中,排序函数已经高度优化,我们直接调用即可。
3.2 滑动窗口遍历
排序后,我们初始化一个大小为k的窗口,从数组开头开始滑动:
- 计算当前窗口的极差(nums[i+k-1] - nums[i])
- 与当前记录的最小极差比较,更新最小值
- 窗口向右滑动一位,重复上述过程
这个过程的复杂度是O(n),因为每个元素最多被访问一次。
3.3 边界条件处理
需要注意几种特殊情况:
- 当k=1时,极差总是0,因为单个元素的最高分和最低分相同
- 当k=n时,极差就是整个数组的最大值减去最小值
- 当数组长度小于k时,题目保证不会出现这种情况(根据提示)
