跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
编程语言java算法

632. 最小区间 - 贪心算法思路与实现

综述由AI生成讲解 LeetCode 第 632 题最小区间的解法。问题要求在 k 个非递减整数列表中找出一个最小区间,使得每个列表至少有一个数在该区间内。核心思路采用贪心算法,维护一个包含各列表当前最小元素的集合,通过不断移除集合中的最小值并替换为对应列表的下一个元素来压缩区间范围,同时记录最优解。文中提供了 C++ 和 Java 两种语言的完整实现代码。

t ag发布于 2026/3/27更新于 2026/5/2322 浏览

632. 最小区间

你有 k 个非递减排列的整数列表。找到一个最小区间,使得 k 个列表中的每个列表至少有一个数包含在其中。

我们定义如果 b-a < d-c 或者在 b-a == d-c 时 a < c,则区间 [a,b] 比 [c,d] 小。

示例

示例 1:

输入:nums = [[4,10,15,24,26], [0,9,12,20], [5,18,22,30]] 输出:[20,24] 解释:列表 1:[4, 10, 15, 24, 26],24 在区间 [20,24] 中。列表 2:[0, 9, 12, 20],20 在区间 [20,24] 中。列表 3:[5, 18, 22, 30],22 在区间 [20,24] 中。

示例 2:

输入:nums = [[1,2,3],[1,2,3],[1,2,3]] 输出:[1,1]

提示

  • nums.length == k
  • 1 <= k <= 3500
  • 1 <= nums[i].length <= 50
  • -10^5 <= nums[i][j] <= 10^5
  • nums[i] 按非递减顺序排列

思路

题目要求给出若干个非递减序列,算出一个区间 [l,r],使得每个序列至少有一个数在区间内。

既然题目要求每个序列中至少有一个数在区间内,那么索性先选取各个序列中最小的数也就是各个序列的首元素构成一个集合,此时,集合内的数就会生成一个区间 [l1,r1],l1 就是所有序列首元素的最小值,r1 就是首元素的最大值。这时候的区间一定满足'每个序列至少有一个数在区间内'的条件,但未必是最小的,之后就要压缩区间。

在压缩区间之前必须明确,在 [l1,r1] 与初始集合的基础上进行压缩,集合内必须保证含有每个序列中的数。而怎么压缩区间就体现了贪心的思想,每次压缩都从集合中弹出最小的数,之后,为了满足'每个序列至少有一个数在区间内'的条件,需要在其所属序列中选择下一个数加入集合,获取新集合的区间对比更新所求区间。

例如:当前从集合中弹出的元素是 nums[i][j],那么就需要将 nums[i][j+1] 加入集合,假设弹出前集合的区间为 [l1,r1],l1 为集合中最小元素,r1 为集合中最大元素,[l1,r1] 为当前压缩到的最小区间,即 ans 区间;加入元素后的新集合对应的新区间为 [l2,r2],此时就要将 ans 与新区间进行对比,如果新区间小于 ans,就更新 ans 为新区间,否则 ans 不动。

为什么每次弹出集合中最小的数,加入其序列中的下一个数?

答:因为题目保证所有序列都为非递减序列,则每次弹出集合中最小的数(也就是 l1),并加入其原序列的下一个数 x,那么 x 一定大于 l1。如果,此时 x 为新集合中最小的数,那么新集合的新区间为 [x,r1] 的长度一定小于原区间长度,又因为 x 是从 l1 的序列中加入集合的,说明弹出、加入的过程不会影响到集合中其他序列的数,也就是一定不会破坏'每个序列至少有一个数在区间内'的条件,所以 [x,r1] 一定是当前满足题意的最小区间,随之更新 ans,从而达到压缩区间的目的;如果此时 x 不为新集合中最小的数,最小的数为 l2,x 可能大于 r1,也可能在 [l2,r1] 之间,此时就要对比新集合的新区间与 ans 的大小,判断是否更新 ans 同样可以压缩区间。即使某个序列中有多个数在区间也无所谓,只要满足'每个序列至少有一个数在区间内'的条件即可。

至此,不断弹出,加入元素,保证集合内元素个数不变,不断在贪心的基础上压缩,直到集合不可再压缩,返回 ans 区间。

代码实现

C++ 实现

class Solution {
public:
    typedef struct node{
        int data;//当前元素数据
        int i;//原序列位置
        int idx;//所在原序列下标
        bool operator < (const node& a)const {
            if (data == a.data) {
                return i < a.i;
            }
            return data < a.data;
        }
    }Node;

    vector<int> smallestRange(vector<vector<int>>& nums) {
        vector<int> ans;
        if (nums.empty()) {
            return ans;
        }
        set<Node> s;
        for (int i = 0; i < nums.size(); i++) {
            //初始化集合,将每个序列最小数加入集合
            if (nums[i].empty()) {
                continue;
            }
            Node t = { nums[i][0],i,0 };
            s.insert(t);
        }
        if (s.empty()) {
            return ans;
        }
        int l = (*s.begin()).data;
        int r = (*s.rbegin()).data;
        //压缩区间
        while (1) {
            auto it = s.begin();
            int i = (*it).i;
            int idx = (*it).idx;
            if (idx == nums[i].size() - 1) {
                //最小元素弹出后无法再加入元素
                break;//跳出循环,压缩结束
            } else {
                s.erase(s.begin());
                Node t = { nums[i][idx + 1],i,idx + 1 };
                s.insert(t);
                if (((*s.rbegin()).data - (*s.begin()).data) < (r - l)) {
                    //遇到更小的区间,更新
                    r = (*s.rbegin()).data;
                    l = (*s.begin()).data;
                } else if (((*s.rbegin()).data - (*s.begin()).data) == (r - l)) {
                    //同样长度的区间选择字典序更小的,更新
                    if ((*s.begin()).data < l) {
                        r = (*s.rbegin()).data;
                        l = (*s.begin()).data;
                    }
                }
            }
        }
        ans.push_back(l);
        ans.push_back(r);
        return ans;
    }
};

Java 实现

class Solution {
    public class Node implements Comparable<Node> {
        int data;
        int i;
        int idx;
        public Node(int data, int i, int idx) {
            this.data = data;
            this.i = i;
            this.idx = idx;
        }
        public int compareTo(Node a){
            if(this.data==a.data){
                return this.i-a.i;
            }
            return this.data-a.data;
        }
    }

    public int[] smallestRange(List<List<Integer>> nums) {
        int ans[]=new int[2];
        if(nums.size()==0){
            return ans;
        }
        TreeSet<Node> s=new TreeSet<>();
        for (int i = 0; i < nums.size(); i++) {
            if(nums.get(i).size()==0){
                continue;
            }
            Node t=new Node(nums.get(i).get(0),i,0);
            s.add(t);
        }
        if(s.size()==0){
            return ans;
        }
        int l=s.first().data;
        int r=s.last().data;
        while(true){
            Node it=s.first();
            int i=it.i;
            int idx=it.idx;
            if(idx==nums.get(i).size()-1){
                break;
            } else{
                s.remove(s.first());
                Node t=new Node(nums.get(i).get(idx+1),i,idx+1);
                s.add(t);
                int len=s.last().data-s.first().data+1;
                if(len<(r-l+1)){
                    l=s.first().data;
                    r=s.last().data;
                } else if(len==(r-l+1)){
                    if(l>s.getFirst().data){
                        l=s.first().data;
                        r=s.last().data;
                    }
                }
            }
        }
        ans[0]=l;
        ans[1]=r;
        return ans;
    }
}

目录

  1. 632. 最小区间
  2. 示例
  3. 提示
  4. 思路
  5. 代码实现
  6. C++ 实现
  7. Java 实现
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 基于 Vulkan 的游戏引擎平面反射实现方案
  • CentOS 系统定时执行 Python 邮件发送任务的五种方案
  • 通过 Logit Bias 精细调控大模型词汇生成
  • AI 智能填表助手:基于大模型的 Web 表单自动填写工具
  • Web 转 Android APK:基于 Docker 的自动化打包实践
  • C++ 智能指针详解:RAII 原理与标准库实现
  • Nginx 入门详解:从基础配置到高性能实战
  • SpringAI 集成 Ollama 与 Deepseek 构建本地对话机器人 (二)
  • Python 核心技术点汇总:装饰器、拷贝及数据结构
  • Java RESTful 接口开发最佳实践
  • 黑马点评项目实战:Redis 缓存策略与 RabbitMQ 异步秒杀
  • Linux 网络编程实战:HTTP 协议解析与 C++ 服务器实现
  • Linux 环境下使用 C++ 实现 Shell 基本功能
  • Python 爬虫结合 AI 绘画模型自动化采集艺术素材
  • Docker 容器操作与实战指南
  • VSCode Copilot 自定义指令配置与开发效率提升实践
  • Agent 在提示工程中的应用:从思维链到 ReAct
  • JVM GC 核心解析:收集器、GC 类型与四种垃圾回收算法
  • 二分查找应用:山峰数组的峰顶索引与寻找峰值
  • 家庭 AI 助手搭建:QQ 机器人接入 OpenClaw

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online