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

推荐订阅源

Project Zero
Project Zero
Security Archives - TechRepublic
Security Archives - TechRepublic
C
Cyber Attacks, Cyber Crime and Cyber Security
Security Latest
Security Latest
Scott Helme
Scott Helme
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
V
Vulnerabilities – Threatpost
C
CERT Recently Published Vulnerability Notes
S
Schneier on Security
G
GRAHAM CLULEY
L
Lohrmann on Cybersecurity
D
Darknet – Hacking Tools, Hacker News & Cyber Security
I
Intezer
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
F
Full Disclosure
T
The Exploit Database - CXSecurity.com
P
Proofpoint News Feed
WordPress大学
WordPress大学
Microsoft Azure Blog
Microsoft Azure Blog
H
Help Net Security
大猫的无限游戏
大猫的无限游戏
MyScale Blog
MyScale Blog
Hacker News: Ask HN
Hacker News: Ask HN
G
Google Developers Blog
H
Heimdal Security Blog
O
OpenAI News
Hugging Face - Blog
Hugging Face - Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
L
LangChain Blog
C
Cisco Blogs
云风的 BLOG
云风的 BLOG
IT之家
IT之家
Cyberwarzone
Cyberwarzone
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Know Your Adversary
Know Your Adversary
博客园 - 聂微东
The Cloudflare Blog
C
Check Point Blog
K
Kaspersky official blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
月光博客
月光博客
T
Tor Project blog
T
Threat Research - Cisco Blogs
T
Tailwind CSS Blog
P
Proofpoint News Feed
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
A
About on SuperTechFans
小众软件
小众软件
Cloudbric
Cloudbric
A
Arctic Wolf

博客园 - 小纸条

模型微调 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;
    }
}