【每日算法】Day 9-1:贪心算法精讲——区间调度与最优选择(C++实现)
掌握高效决策的核心思想!今日深入解析贪心算法的底层逻辑,聚焦区间调度与最优选择两大高频场景,结合大厂真题与严谨证明,彻底掌握“局部最优即全局最优”的算法哲学。
一、贪心算法核心思想
贪心算法(Greedy Algorithm) 是一种在每一步选择中都采取当前状态下最优决策的算法,核心特性:
局部最优性:每一步选择当前最优解
不可回溯性:选择后不可更改之前的决策
高效性:通常时间复杂度较低
适用场景:
-
问题具有最优子结构
-
贪心策略能导致全局最优解(需数学证明)
-
常见于调度、分配、覆盖等问题
与动态规划的区别:
-
贪心:不可回退,通常更高效
-
DP:保留所有可能,保证全局最优
二、区间调度问题
1. 无重叠区间(LeetCode 435)
问题描述:
给定多个区间,移除最少数量的区间使剩余区间互不重叠
贪心策略:
-
按结束时间排序,优先选择结束早的区间
-
每次选择与已选区间不冲突的最小区间
C++实现:
int eraseOverlapIntervals(vector<vector<int>>& intervals) {if (intervals.empty()) return 0;// 按结束时间升序排序sort(intervals.begin(), intervals.end(), [](auto& a, auto& b) { return a[1] < b[1]; });int count = 1, end = intervals[0][1];for (int i=1; i<intervals.size(); ++i) {if (intervals[i][0] >= end) { // 不重叠count++;end = intervals[i][1];}}return intervals.size() - count;
}
2. 合并区间(LeetCode 56)
问题描述:
合并所有重叠区间
贪心策略:
按起始时间排序,依次合并重叠区间
vector<vector<int>> merge(vector<vector<int>>& intervals) {if (intervals.empty()) return {};// 按起始时间排序sort(intervals.begin(), intervals.end());vector<vector<int>> res;res.push_back(intervals[0]);for (int i=1; i<intervals.size(); ++i) {if (intervals[i][0] <= res.back()[1]) { // 重叠res.back()[1] = max(res.back()[1], intervals[i][1]);} else {res.push_back(intervals[i]);}}return res;
}
三、最优选择问题
1. 跳跃游戏(LeetCode 55)
问题描述:
数组元素表示最大跳跃长度,判断能否到达终点
贪心策略:
维护当前能到达的最远距离
bool canJump(vector<int>& nums) {int maxReach = 0;for (int i=0; i<nums.size(); ++i) {if (i > maxReach) return false; // 无法到达当前位置maxReach = max(maxReach, i + nums[i]);if (maxReach >= nums.size()-1) return true;}return true;
}
2. 分发糖果(LeetCode 135)
问题描述:
每个孩子至少1颗糖,评分高的孩子必须比相邻孩子糖多
贪心策略:
左右两次遍历,分别满足左右规则
int candy(vector<int>& ratings) {int n = ratings.size();vector<int> candies(n, 1);// 从左到右:右分高于左分则+1for (int i=1; i<n; ++i) {if (ratings[i] > ratings[i-1])candies[i] = candies[i-1] + 1;}// 从右到左:左分高于右分则取maxfor (int i=n-2; i>=0; --i) {if (ratings[i] > ratings[i+1])candies[i] = max(candies[i], candies[i+1]+1);}return accumulate(candies.begin(), candies.end(), 0);
}
四、正确性证明方法
| 证明方法 | 适用场景 | 示例问题 |
|---|---|---|
| 交换论证 | 排序类问题 | 区间调度 |
| 数学归纳法 | 递推型决策问题 | 跳跃游戏 |
| 剪切粘贴 | 存在更优解则矛盾 | 任务调度 |
| 贪心选择性质 | 证明第一步选择不影响最优解 | 霍夫曼编码 |
五、大厂真题实战
真题1:任务调度器(LeetCode 621)
题目描述:
给定任务列表和冷却时间n,求最短执行时间
贪心策略:
优先安排出现次数最多的任务
int leastInterval(vector<char>& tasks, int n) {vector<int> cnt(26, 0);for (char c : tasks) cnt[c-'A']++;sort(cnt.begin(), cnt.end(), greater<int>());int maxCnt = cnt[0], emptySlots = (maxCnt-1)*n;for (int i=1; i<26; ++i) {emptySlots -= min(cnt[i], maxCnt-1);}return tasks.size() + max(0, emptySlots);
}
真题2:加油站问题(LeetCode 134)
题目描述:
环形路线上找到能绕行一圈的起点
贪心策略:
-
总油量不足直接返回-1
-
局部油量不足则重置起点
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {int total = 0, curr = 0, start = 0;for (int i=0; i<gas.size(); ++i) {total += gas[i] - cost[i];curr += gas[i] - cost[i];if (curr < 0) {start = i + 1;curr = 0;}}return total >= 0 ? start : -1;
}
六、常见误区与优化技巧
-
策略错误:未严格证明贪心选择的正确性
-
排序方式错误:区间问题未选择正确的排序键
-
状态维护遗漏:跳跃游戏未及时更新最远距离
-
优化技巧:
-
预处理排序降低复杂度
-
空间优化(如用变量替代数组)
-
合并遍历减少循环次数
-
七、总结与扩展
核心优势:
-
时间复杂度通常为O(n log n)
-
代码简洁高效,适合笔试场景
-
解决资源分配问题的利器
局限性:
-
无法保证所有问题全局最优
-
需要严格的数学证明
LeetCode真题训练:
-
452. 用最少数量的箭引爆气球
-
406. 根据身高重建队列
-
122. 买卖股票的最佳时机 II
相关文章:
【每日算法】Day 9-1:贪心算法精讲——区间调度与最优选择(C++实现)
掌握高效决策的核心思想!今日深入解析贪心算法的底层逻辑,聚焦区间调度与最优选择两大高频场景,结合大厂真题与严谨证明,彻底掌握“局部最优即全局最优”的算法哲学。 一、贪心算法核心思想 贪心算法(Greedy Algorit…...
构建稳健的机器学习系统:应对数据偏移挑战
构建稳健的机器学习系统:应对数据偏移挑战 1. 引言:数据偏移类型与挑战 在机器学习系统从实验室到生产环境的转变过程中,数据偏移(Data Shift)是最常见也最具挑战性的问题之一。所谓数据偏移,指的是训练数…...
从零构建大语言模型全栈开发指南:第二部分:模型架构设计与实现-2.1.3前馈网络(FFN)与激活函数(GELU)优化
👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 2.1.3 前馈网络(FFN)与激活函数(GELU)优化1. 前馈网络(FFN)的架构设计与数学原理1.1 FFN在Transformer中的核心作用2. GELU激活函数的数学特性与优化2.1 GELU的数学形式与近似计算3. 逐行代码实现…...
3个版本的Unity项目的异同
根据搜索结果,以下是关于 SPR 3D Sample Scene(URP)、SPR Universal 3D 和 3D(Built-In Render Pipeline) 的定义及区别分析: 1. 定义与用途 SPR 3D Sample Scene(URP) 是基于 Universal Render Pipeline (URP) 的 3D 示例场景,专为展示 URP …...
组态软件之万维组态介绍(web组态、html组态、vue2/vue3组态、组态软件、组态编辑器)
一、什么是组态软件 组态软件是一种用于创建、配置和管理监控和控制系统的软件工具。组态是指不需要编写计算机程序、通过配置的方式完成工业应用开发的系统。它们通常用于工业自动化领域,用于实时监视和控制工业过程。组态软件提供了丰富的功能和工具,使…...
Linux系统perf命令使用介绍,如何用此命令进行程序热点诊断和性能优化
Linux perf 命令使用指南:程序热点诊断与性能优化 perf 是 Linux 系统上一个强大的性能分析工具,它能够帮助开发者进行程序热点诊断和性能优化。下面详细介绍 perf 的使用方法。 1. perf 简介 perf (Performance Event Counters) 是 Linux 内核提供的…...
《Linux运维实战:Ubuntu 22.04使用pam_faillock实现登录失败处理策略》
总结:整理不易,如果对你有帮助,可否点赞关注一下? 更多详细内容请参考:Linux运维实战总结 一、背景信息 在ubuntu 22.04中,pam_tally2模块已被弃用,取而代之的是pam_faillock模块。因此…...
AI Agent开发大全第八课-Stable Diffusion 3的本地安装全步骤
前言 就像我们前面几课所述,本系列是一门体系化的教学,它不像网上很多个别存在的单篇博客走“吃快餐”模式,而是从扎实的基础来带领大家一步步迈向AI开发高手。所以我们的AI课程设置是相当全面的,除了有牢固的基础知识外还有外面互联网上也搜不到的生产级实战。 前面讲过…...
Spring MVC 深度解析:原理、源码剖析与实战
Spring MVC 深度解析:原理、源码剖析与实战 在 Spring 体系中,Spring MVC 作为 Web 层的核心框架,承担着请求处理、参数解析、视图渲染等关键任务。今天,我们将深入剖析 Spring MVC 的执行流程,结合 源码分析…...
347 前k个高频元素
步骤1:统计元素频率 使用哈希表(unordered_map)统计每个元素的出现次数,时间复杂度为 O(n)。 步骤2:构建最小堆维护Top K 优先队列(最小堆):用priority_queue维护当前频率最高的k…...
BUUCTF-web刷题篇
1.EASYSQL破解密码 万能公式: 1 and 11 1 and 11 1 or 11 1 or 11 解释:payload SELECT * FROM tables WHERE username1 or 11 and password1 or 11 优先级排序:and 优先级高于 or,所以要计算 and 然后再计算 or username1…...
LeetCode 第31~33题
目录 LeetCode 第31题:下一个排列 LeetCode 第32题:最长有效括号 LeetCode 第33题:搜索旋转排序数组 LeetCode 第31题:下一个排列 题目描述 整数数组的一个排列就是将所有成员以序列或线性顺序排列。例如arr[1,2,3],以…...
【NLP 44、实践 ⑪ 用Bert模型结构实现自回归语言模型的训练】
目录 数据文件 一、模型定义 1.模型初始化 代码运行流程 2.前向传播,计算损失 ⭐ 代码运行流程 二、加载语料 代码运行流程 三、 随机生成样本 代码运行流程 四、建立模型 五、采样策略选择 代码运行流程 六、模型效果测试 代码运行流程 七、模型训练 代码运行流程 …...
Go 语言规范学习(1)
文章目录 IntroductionNotation示例(Go 语言的 if 语句): Source code representationCharacters例子:变量名可以是中文 Letters and digits Lexical elementsCommentsTokensSemicolons例子:查看程序所有的token Ident…...
ShapeCrawler:.NET开发者的PPTX操控魔法
引言 在当今的软件开发领域,随着数据可视化和信息展示需求的不断增长,处理 PPTX 文件的场景日益频繁。无论是自动化生成报告、批量制作演示文稿,还是对现有 PPT 进行内容更新与格式调整,开发者都需要高效的工具来完成这些任务。传…...
微信小程序如何接入直播功能
一、小程序直播开通背景 1.政府资质要求 政府的要求,小程序开通直播需要注册主体具备互联网直播的资质,普通企业需要《信息网络传播视听节目许可证》,表演性质的直播需要《网络文化经营许可证》,政府主体需要《社会信用代码》及…...
ArrayList<E>案例//定义一个方法,将价格低于3000的手机信息返回
import java.util.ArrayList;public class ArrayListphone {public static void main(String[] args){//定义一个方法,将价格低于3000的手机信息返回Phone p1new Phone("小米",1000);Phone p2new Phone("苹果",8000);Phone p3new Phone("锤…...
基于Spring Boot的停车场管理系统的设计与实现(LW+源码+讲解)
专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…...
慧通测控汽车智能座舱测试技术
一、引言 随着科技的飞速发展,汽车正从单纯的交通工具向智能化移动空间转变。智能座舱作为这一转变的核心体现,融合了多种先进技术,为用户带来前所未有的驾驶体验。从简单的信息娱乐系统到高度集成的人机交互、智能驾驶辅助以及车辆状态监测…...
Qt进程间通信:QSharedMemory 使用详解
1. 什么是 QSharedMemory? QSharedMemory 是 Qt 中用于进程间共享内存的类。它允许多个进程共享一块内存区域,从而避免数据传输时的 IO 操作,提高通信速度。通过共享内存,多个进程可以直接读写这块内存,而无需经过文件…...
kettle插件-rabbitmq插件
场景:kettle本身可以直接链接rabbitmq,但是需要配置rabbitmq开启mqtt协议,本次讲解下自定义开发组件RabbitMQ consumer,无需开启mqtt协议即可使用。 1、docker 安装rabbitmq 1)下载镜像 docker pull rabbitmq 2&…...
为Windows10的WSL Ubuntu启动sshd服务并使用Trae远程连接
Windows10的WSL Ubuntu,使用起来非常方便,但是美中不足的是,无法从Windows主机ssh到Ubuntu 。 解决的方法是在Ubuntu安装sshd服务 Ubuntu安装sshd服务 执行命令 sudo apt install openssh-server 安装好后,先本地测试&#x…...
【C#.NET】VS2022创建Web API项目
C# Web API 是一种基于 .NET 平台(包括但不限于.NET Framework 和 .NET Core)构建 HTTP 服务的框架,用于创建 RESTful Web 服务。REST(Representational State Transfer)是一种软件架构风格,它利用HTTP协议…...
体育直播系统趣猜功能开发技术实现方案
功能概述 趣猜功能是“东莞梦幻网络科技”体育直播系统源码中的互动功能,主播可以发起竞猜题目,观众使用虚拟货币进行投注,增加直播间的互动性和趣味性。所有货币均为虚拟货币,通过系统活动获取,不可充值提现。 数据…...
33.[前端开发-JavaScript基础]Day10-常见事件-鼠标事件-键盘事件-定时器-案例
1 window定时器 window定时器方法 setTimeout的使用 setInterval的使用 2 轮播消息提示 案例实战一 – 轮播消息提示 3 关闭隐藏消息 案例实战二 – 关闭隐藏消息 4 侧边栏展示 案例实战三 – 侧边栏展示 5 tab切换实现 案例实战四 – 登录框(作业)…...
C# 多标签浏览器 谷歌内核Csharp
采用框架 :FBrowserCEF3lib 视频演示:点我直达 成品下载: https://wwms.lanzouo.com/iYOd42rl8vje...
如何同步fork的更新
当你fork了一个代码仓库后,要将其与原始源码保持同步,可以按照以下步骤进行操作: 1. 添加原始仓库作为远程源 在本地命令行中,进入到你fork后的代码仓库目录,然后使用以下命令添加原始仓库(通常称为upstr…...
如何从0设计开发一款JS-SDK
一、前言 前端SDK是什么?前端SDK是为了帮助前端实现特定需求,而向开发者暴露的一些JS-API的集合,规范的SDK包括若干API实现、说明文档等 前端SDK其实很常见了,比如: UI组件库:通过封装一系列组件ÿ…...
linux实现rsync+sersync实时数据备份
1.概述 rsync(Remote Sync) 是一个Unix/linux系统下的文件同步和传输工具 2.端口和运行模式 tcp/873 采用C/S模式(客户端/服务器模式) 3.特点 可以镜像保存整个目录和文件第一次全量备份(备份全部的文件),之后是增量备份(只备份变化的文件) 4. 数…...
【计算机网络】计算机网络协议、接口与服务全面解析——结合生活化案例与图文详解
协议、接口与服务 导读一、协议1.1 定义1.2 组成 二、接口三、服务3.1 定义3.2 服务与协议的区别3.3 分类3.3.1 面向连接服务于无连接服务3.3.2 可靠服务和不可靠服务3.3.3 有应答服务和无应答服务 结语 导读 大家好,很高兴又和大家见面啦!!…...
