1. 题目解析与解题思路
- 学生分数的最小差值这道题目要求我们从一个学生分数数组中,找出任意k个学生分数的最小极差(最大值与最小值的差)。这类极值问题在算法面试中非常常见,特别是在金融风控、成绩分析等实际场景中有广泛应用。
1.1 问题本质理解
这道题的核心在于:给定一个无序数组,我们需要从中选择k个元素,使得这k个元素的最大值与最小值之差最小。换句话说,我们需要找到一个最"紧凑"的k元素子集。
举个例子:
- 输入:[9,4,1,7], k=2
- 排序后:[1,4,7,9]
- 可能的2元素组合差值:
- 1和4 → 3
- 4和7 → 3
- 7和9 → 2
- 最小差值为2
1.2 解题思路分析
解决这个问题主要有两种思路:
-
排序+滑动窗口:
- 先对数组排序,这样相邻元素的差值会更小
- 使用固定长度为k的滑动窗口遍历数组
- 计算每个窗口的首尾差值(即极差)
- 记录最小差值
-
排序+贪心:
- 同样是先排序
- 然后遍历数组,对于每个元素nums[i],计算它与前面k-1个元素的差值
- 记录最小差值
这两种方法的时间复杂度都是O(nlogn),主要来自排序步骤。后续的遍历都是O(n)时间。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 解法一:排序+滑动窗口详解
2.1 算法步骤拆解
- 排序数组:这是关键的第一步,将无序数组变为有序,这样相邻元素的差值最小化
- 初始化窗口:设置窗口左边界left=0,右边界right=k-1
- 滑动窗口:
- 计算当前窗口的差值nums[right]-nums[left]
- 与当前最小值比较并更新
- 窗口整体右移一位
- 返回结果:遍历完成后得到的最小差值
2.2 Java代码实现
java复制class Solution {
public int minimumDifference(int[] nums, int k) {
Arrays.sort(nums);
int n = nums.length;
int ret = Integer.MAX_VALUE;
for(int right = k-1, left = 0; right < n; right++) {
ret = Math.min(ret, nums[right] - nums[left]);
left++;
}
return ret;
}
}
2.3 关键点解析
- 排序的必要性:如果不排序,我们需要检查所有C(n,k)种组合,时间复杂度会爆炸
- 窗口大小的控制:窗口长度固定为k,每次移动一个单位
- 边界条件处理:当k=1时,差值为0;当k=n时,差值为最大元素-最小元素
- 初始值设置:ret初始化为Integer.MAX_VALUE确保第一次比较能更新
提示:在实际面试中,建议先明确说明为什么要排序,这是解题的关键洞察点。
3. 解法二:排序+贪心策略详解
3.1 算法优化思路
解法二
