惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Spread Privacy
Spread Privacy
S
Schneier on Security
G
GRAHAM CLULEY
AWS News Blog
AWS News Blog
Cisco Talos Blog
Cisco Talos Blog
The Hacker News
The Hacker News
T
The Exploit Database - CXSecurity.com
P
Proofpoint News Feed
L
LINUX DO - 热门话题
C
CXSECURITY Database RSS Feed - CXSecurity.com
Security Latest
Security Latest
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Google DeepMind News
Google DeepMind News
H
Hacker News: Front Page
PCI Perspectives
PCI Perspectives
T
Tenable Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
N
Netflix TechBlog - Medium
Application and Cybersecurity Blog
Application and Cybersecurity Blog
腾讯CDC
A
Arctic Wolf
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Project Zero
Project Zero
NISL@THU
NISL@THU
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
V
Vulnerabilities – Threatpost
Cyberwarzone
Cyberwarzone
I
Intezer
Apple Machine Learning Research
Apple Machine Learning Research
T
Threat Research - Cisco Blogs
爱范儿
爱范儿
Webroot Blog
Webroot Blog
Forbes - Security
Forbes - Security
The Cloudflare Blog
T
Tailwind CSS Blog
C
CERT Recently Published Vulnerability Notes
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
大猫的无限游戏
大猫的无限游戏
Microsoft Azure Blog
Microsoft Azure Blog
Know Your Adversary
Know Your Adversary
云风的 BLOG
云风的 BLOG
B
Blog
The Register - Security
The Register - Security
T
Threatpost
C
Cybersecurity and Infrastructure Security Agency CISA
V2EX - 技术
V2EX - 技术
P
Privacy & Cybersecurity Law Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org

博客园 - 小纸条

模型微调 ruoyiai 启动指南 反向传播 numpy的使用 B 和 B+树 红黑树 ruoyi-vue 梯度下降法 博弈论 离散化 AcWing 906. 区间分组 AcWing 908 最大不相交区间数量 AcWing 905. 区间选点 AcWing 104. 货仓选址 动态规划经典题 窗口函数 1226. 哲学家进餐 1195. 交替打印字符串 1117. H2O 生成 1116. 打印零与奇偶数 关联子查询
AcWing 907. 区间覆盖
小纸条 · 2025-11-22 · via 博客园 - 小纸条

AcWing 907. 区间覆盖

一、题目核心

  • 给定目标线段区间 [s, t]N 个闭区间,选择最少数量的区间完全覆盖目标线段,无法覆盖则输出 -1
  • 数据范围:1 ≤ N ≤ 10^5,区间端点可取值范围 [-10^9, 10^9]

二、核心解法:贪心算法

核心思路

按左端点排序后,每次在能覆盖当前起点的区间中,选择右端点最大的区间,最大化覆盖范围,从而最小化区间使用数量。

具体步骤

AcWing 907 “区间覆盖”问题(即:用最少的给定区间完全覆盖目标区间 [s, t])在 Java 中的经典实现如下。该解法采用贪心策略 + 双指针,时间复杂度为 O(n log n)(主要来自排序)。


✅ 题目回顾

  • 输入
    • 目标区间 [s, t]
    • N 个候选闭区间 [a_i, b_i]
  • 输出
    • 能完全覆盖 [s, t] 所需的最少区间数
    • 若无法覆盖,输出 -1

✅ Java 实现(标准写法)

import java.util.*;

public class Main {
    static class Interval {
        int l, r;
        Interval(int l, int r) {
            this.l = l;
            this.r = r;
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int s = sc.nextInt();
        int t = sc.nextInt();
        int n = sc.nextInt();
        
        Interval[] intervals = new Interval[n];
        for (int i = 0; i < n; i++) {
            int a = sc.nextInt();
            int b = sc.nextInt();
            intervals[i] = new Interval(a, b);
        }

        // 按左端点升序排序
        Arrays.sort(intervals, (o1, o2) -> Integer.compare(o1.l, o2.l));

        int res = 0;          // 使用的区间数量
        int currentEnd = s;   // 当前已覆盖到的位置
        int i = 0;            // 遍历指针

        while (currentEnd < t) {
            int maxRight = currentEnd; // 在能覆盖 currentEnd 的区间中找最远右端点

            // 找所有左端点 <= currentEnd 的区间,并记录最大右端点
            while (i < n && intervals[i].l <= currentEnd) {
                if (intervals[i].r > maxRight) {
                    maxRight = intervals[i].r;
                }
                i++;
            }

            // 如果无法向右扩展,说明覆盖失败
            if (maxRight == currentEnd) {
                System.out.println(-1);
                return;
            }

            // 选择这个最远的区间
            res++;
            currentEnd = maxRight; // 更新已覆盖的右边界
        }

        System.out.println(res);
    }
}

🔍 算法逻辑说明

  1. 排序:按区间左端点 l 升序排列,确保我们从左到右处理。
  2. 贪心扩展
    • 维护当前已覆盖到的位置 currentEnd(初始为 s)。
    • 在所有满足 l <= currentEnd 的区间中,选择 r 最大的那个(即延伸最远)。
  3. 失败判断
    • 如果一轮扫描后 maxRight 没有超过 currentEnd,说明出现“空隙”,无法继续覆盖。
  4. 终止条件:当 currentEnd >= t 时,成功覆盖目标区间。

🧪 示例测试

输入

1 5
3
-1 3
2 4
3 5

执行过程

  • 排序后区间:[-1,3], [2,4], [3,5]
  • 第1轮:currentEnd=1,可选 [-1,3]maxRight=3res=1
  • 第2轮:currentEnd=3,可选 [2,4], [3,5]maxRight=5res=2
  • 5 >= 5,结束,输出 2

✅ 输出:2


⚠️ 注意事项

  • 区间是闭区间,所以 l <= currentEnd 是合法的。
  • 必须处理无法覆盖的情况(如中间有空隙或所有区间都在目标左侧/右侧)。
  • 不要漏掉 i++ 的推进逻辑,否则会死循环。

类似题目:https://leetcode.cn/problems/video-stitching/submissions/679961490/

class Solution {
    class Interval{
        private int l;
        private int r;

        public Interval(int l, int r) {
            this.l = l;
            this.r = r;
        }
    }
     public int videoStitching(int[][] clips, int t) {
        int n = clips.length;
        Interval[] intervals = new Interval[n];
        for (int i = 0; i < n; i++) {
            intervals[i]=new Interval(clips[i][0],clips[i][1]);
        }
        // 按左端点升序排序
        Arrays.sort(intervals, Comparator.comparingInt(o -> o.l));

        int res = 0;          // 使用的区间数量
        int currentEnd = 0;   // 当前已覆盖到的位置
        int i = 0;            // 遍历指针

        while (currentEnd < t) {
            int maxRight = currentEnd; // 在能覆盖 currentEnd 的区间中找最远右端点

            // 找所有左端点 <= currentEnd 的区间,并记录最大右端点
            while (i < n && intervals[i].l <= currentEnd) {
                if (intervals[i].r > maxRight) {
                    maxRight = intervals[i].r;
                }
                i++;
            }

            // 如果无法向右扩展,说明覆盖失败
            if (maxRight == currentEnd) {
                return -1;
            }

            // 选择这个最远的区间
            res++;
            currentEnd = maxRight; // 更新已覆盖的右边界
        }
        return res;
    }
}