【LeetCode 每日一题】1984. 学生分数的最小差值

Problem: 1984. 学生分数的最小差值

文章目录

  • 整体思路
      • [1. 核心问题](#1. 核心问题)
      • [2. 算法逻辑:排序 + 滑动窗口](#2. 算法逻辑:排序 + 滑动窗口)
  • 完整代码
  • 时空复杂度
      • [1. 时间复杂度: O ( N log ⁡ N ) O(N \log N) O(NlogN)](#1. 时间复杂度: O ( N log ⁡ N ) O(N \log N) O(NlogN))
      • [2. 空间复杂度: O ( log ⁡ N ) O(\log N) O(logN)](#2. 空间复杂度: O ( log ⁡ N ) O(\log N) O(logN))

整体思路

1. 核心问题

我们需要从数组 nums 中选出 k 个元素,使得这 k 个元素中最大值最小值的差(即极差)最小。

2. 算法逻辑:排序 + 滑动窗口

  • 为什么需要排序?

    • 如果数组是乱序的,任意选 k 个数,我们很难直观判断哪组数的差值最小。
    • 但是,如果我们把数组从小到大排序,那么数值相近的元素就会挨在一起。
    • 在排序后的数组中,为了让 max - min 最小,选取的 k 个数必然是连续 的。
      • 例如:在 [1, 4, 7, 9] 中选 3 个数。选 [1, 4, 7] 优于选 [1, 7, 9],因为后者跨度更大。
    • 因此,问题转化为:在排序后的数组中,找到一个长度为 k 的连续子数组(滑动窗口),使其末尾元素(该窗口最大值)与开头元素(该窗口最小值)的差值最小。
  • 具体步骤

    1. 排序 :使用 Arrays.sort(nums) 对数组进行升序排列。
    2. 滑动窗口遍历
      • 窗口大小固定为 k
      • 窗口的左边界为 i,右边界为 i + k - 1
      • 在该窗口内,最大值是 nums[right],最小值是 nums[left]
      • 计算差值 diff = nums[i + k - 1] - nums[i]
      • 遍历所有可能的窗口,维护全局最小的 diff

完整代码

java 复制代码
import java.util.Arrays;

class Solution {
    public int minimumDifference(int[] nums, int k) {
        // 1. 排序
        // 将数组按从小到大排序,这是使用滑动窗口策略的前提
        Arrays.sort(nums);
        
        // 初始化结果为整型最大值,用于后续找最小值
        int ans = Integer.MAX_VALUE;
        
        
        // 2. 滑动窗口遍历
        // i 代表当前窗口的起始位置(最小值位置)
        // i + k - 1 代表当前窗口的结束位置(最大值位置)
        // 循环条件 i < nums.length - k + 1 保证窗口右边界不越界
        for (int i = 0; i < nums.length - k + 1; i++) {
            // 计算当前窗口的极差:最大值 - 最小值
            // 由于已排序,最大值一定是窗口最右侧,最小值是窗口最左侧
            int currentDiff = nums[i + k - 1] - nums[i];
            
            // 更新全局最小差值
            ans = Math.min(ans, currentDiff);
        }
        
        return ans;
    }
}

时空复杂度

假设数组 nums 的长度为 N N N。

1. 时间复杂度: O ( N log ⁡ N ) O(N \log N) O(NlogN)

  • 排序Arrays.sort 使用双轴快速排序(对于基本类型),时间复杂度为 O ( N log ⁡ N ) O(N \log N) O(NlogN)。这是算法中耗时最主要的部分。
  • 遍历 :滑动窗口遍历只需一次线性扫描,时间复杂度为 O ( N ) O(N) O(N)(具体循环次数为 N − k + 1 N - k + 1 N−k+1)。
  • 总计 : O ( N log ⁡ N ) + O ( N ) = O ( N log ⁡ N ) O(N \log N) + O(N) = O(N \log N) O(NlogN)+O(N)=O(NlogN)。

2. 空间复杂度: O ( log ⁡ N ) O(\log N) O(logN)

  • 计算依据
    • 代码只使用了常数个额外变量 (ans, i)。
    • 但是,Java 的 Arrays.sort 对于基本数据类型 int[] 是原地排序,其内部递归调用栈需要消耗 O ( log ⁡ N ) O(\log N) O(logN) 的空间。
  • 结论 : O ( log ⁡ N ) O(\log N) O(logN)。
相关推荐
九.九8 小时前
CANN HCOMM 底层机制深度解析:集合通信算法实现、RoCE 网络协议栈优化与多级同步原语
网络·网络协议·算法
C++ 老炮儿的技术栈8 小时前
Qt Creator中不写代如何设置 QLabel的颜色
c语言·开发语言·c++·qt·算法
子春一8 小时前
Flutter for OpenHarmony:构建一个 Flutter 数字消消乐游戏,深入解析网格状态管理、合并算法与重力系统
算法·flutter·游戏
草履虫建模14 小时前
力扣算法 1768. 交替合并字符串
java·开发语言·算法·leetcode·职场和发展·idea·基础
naruto_lnq16 小时前
分布式系统安全通信
开发语言·c++·算法
Jasmine_llq17 小时前
《P3157 [CQOI2011] 动态逆序对》
算法·cdq 分治·动态问题静态化+双向偏序统计·树状数组(高效统计元素大小关系·排序算法(预处理偏序和时间戳)·前缀和(合并单个贡献为总逆序对·动态问题静态化
爱吃rabbit的mq17 小时前
第09章:随机森林:集成学习的威力
算法·随机森林·集成学习
(❁´◡`❁)Jimmy(❁´◡`❁)18 小时前
Exgcd 学习笔记
笔记·学习·算法
YYuCChi18 小时前
代码随想录算法训练营第三十七天 | 52.携带研究材料(卡码网)、518.零钱兑换||、377.组合总和IV、57.爬楼梯(卡码网)
算法·动态规划
不能隔夜的咖喱19 小时前
牛客网刷题(2)
java·开发语言·算法