当前位置: 首页 > news >正文

Section four Homework

最近在刷算法题时,又遇到了一道非常经典的贪心题目:给定若干闭区间,求最少需要多少个点,使得每个区间至少包含一个点。这道题看似简单,却完美展现了贪心策略的用处。

问题描述

输入:
\(n\) 个闭区间 \([l_i, r_i]\)\(1 \le i \le n\)

输出:
最少需要放置多少个点,使得每个区间都至少包含一个点。

例如:

区间:[1,3], [2,5], [4,6]
答案:2(比如在点3和点6处放置)

我的解法:右端点优先,贪心选点

核心思想:
把所有区间按右端点从小到大排序,然后尽可能“晚”地放点——也就是放在当前区间的右端点上。

为什么这样做?

你希望一个点能覆盖尽可能多的后续区间。那么,越靠右放,越容易“错过”后面的区间;而越靠左放,又可能浪费了覆盖能力。
但如果我们在当前未被覆盖的区间中,选择右端点最小的那个,并把点放在它的右端点上,就能保证这个点“刚好”覆盖它,同时最大化对后续区间的潜在覆盖能力。

代码实现(C++)

#include <bits/stdc++.h>
using namespace std;struct Interval {int left, right;
};bool cmp(const Interval& a, const Interval& b) {return a.right < b.right; // 按右端点升序
}int main() {int n;cin >> n;vector<Interval> intervals(n);for (int i = 0; i < n; ++i) {cin >> intervals[i].left >> intervals[i].right;}sort(intervals.begin(), intervals.end(), cmp);int pointCount = 0;int lastPoint = -1; // 上一个放置的点for (int i = 0; i < n; ++i) {// 如果当前点没被覆盖if (lastPoint < intervals[i].left) {lastPoint = intervals[i].right; // 在右端点放新点pointCount++;}}cout << pointCount << endl;return 0;
}

💡 小提示:判断条件只需 lastPoint < left 即可。因为 lastPoint 始终是非递减的(我们总是往右放点),不可能出现 lastPoint > right 的情况。

为什么贪心是对的?

要证明贪心算法的正确性,通常需要两个关键性质:

  1. 贪心选择性质(Greedy Choice Property)
    存在一个最优解,其中第一个点就放在右端点最小的区间的右端点上。
    证明思路
    假设最优解中第一个点 \(p\) 覆盖了第一个区间 \([l_1, r_1]\),那么 \(p \in [l_1, r_1]\)
    如果我们把 \(p\) 改成 \(r_1\),会发生什么?
    它依然覆盖 \([l_1, r_1]\)
    对于其他被 \(p\) 覆盖的区间 \([l_j, r_j]\),由于我们按 \(r\) 排序,有 \(r_j \ge r_1\)
    又因为 \(p \ge l_j\)\(p \le r_1\),所以 \(l_j \le r_1 \le r_j\),即 \(r_1\) 也在该区间内!

因此,把点移到 \(r_1\) 不会减少覆盖能力,仍是最优解。

  1. 最优子结构(Optimal Substructure)

一旦我们在 \(r_1\) 放了一个点,所有包含 \(r_1\) 的区间都被覆盖了。剩下的未被覆盖的区间构成一个规模更小的相同问题,可以递归/迭代地用同样策略解决。

复杂度分析

排序:\(O(n \log n)\)
遍历选点:\(O(n)\)
总时间复杂度:\(O(n \log n)\)
空间复杂度:\(O(n)\)(存储区间)

效率非常高,适用于大规模数据。

我对贪心算法的理解

贪心算法常常被初学者误解为“随便选看起来好的”,但实际上,贪心是一种需要严格证明的策略。

它的魅力在于简洁高效——没有回溯、没有状态记忆,一步到位;直觉友好——很多贪心策略符合人类的“局部最优”直觉;适用性强——在区间问题、图论(如最小生成树)、编码(霍夫曼)等领域大放异彩。

比如本题如果按左端点排序,或者在左端点放点,就可能得到次优解。贪心的正确性必须通过数学证明来支撑,而不是靠测试样例“蒙对”。

总结

区间选点问题是一个经典的贪心模型;
关键策略:按右端点排序 + 在右端点放点;
正确性由贪心选择性质和最优子结构共同保证;
时间复杂度 \(O(n \log n)\),实用且优雅。

http://www.jsqmd.com/news/116026/

相关文章:

  • 动态规划算法
  • 美团 商家端响应体解密
  • 阅读诗歌:时间的沙漏
  • 杜教筛
  • Rope旋转位置编码解读
  • PCL分割——圆柱分割
  • 人= 具身生命 × 关系网络 × 叙事自我 × 价值选择
  • Item46--需要类型转换时请为模板定义非成员函数
  • 别再踩坑了!6款实测有效的降ai工具推荐,保姆级教你降低ai率!
  • 读不懂诗歌:钟摆的胎动里倒游的鱼群正在翻译冰层
  • [项目]基于正倒排索引的Boost搜索引擎---编写搜索引擎模块 Searcher - 指南
  • 江西南昌住家保姆/不住家保姆品牌TOP5评测!专业认证+服务保障企业榜单发布,品质家政赋能现代家庭生活 - 全局中转站
  • Item45--运用成员函数模板接受所有兼容类型
  • 大数据领域Kafka与Hadoop的协同工作模式
  • 霍华德·马克斯的市场周期定位技巧
  • 别乱花钱了!6款实测有效的降ai工具推荐,学姐教你降低ai率!
  • 强烈推荐 wxWidgets
  • SFTDataset:Verl 单轮Dataset vs rllm 多轮Dataset vs Parallel-R1 Dataset
  • Boost asio定时器
  • 2025年度江西南昌育儿嫂企业TOP5评测!金牌一站式早教型育儿嫂品牌榜单发布,赋能现代家庭育儿新生态 - 全局中转站
  • 2025年度江西南昌老人护理企业TOP7评测!专业照护+经验沉淀优质品牌榜单发布,用心守护构筑长者幸福晚年 - 全局中转站
  • Product Hunt 每日热榜 | 2025-12-20
  • 过半的家庭都踩过近视的“坑”,每位爸妈都值得注意!
  • 每天一个网络知识:什么是光猫?
  • 【2025全网盘点】10款常见降AI率工具大汇总(含笔灵/Kimi等免费降AI版本)
  • Item28--避免返回 handles 指向对象内部成分
  • 前端开发随笔
  • 基于java的SpringBoot/SSM+Vue+uniapp的大学生学业预警和警告平台的详细设计和实现(源码+lw+部署文档+讲解等)
  • 一文吃透动态规划解题思路——以钢条切割问题为例
  • Redis:安装配置、核心概念与实践应用