【左程云算法全讲11】贪心算法 并查集

news2024/12/22 20:47:18

系列综述:
💞目的:本系列是个人整理为了秋招面试的,整理期间苛求每个知识点,平衡理解简易度与深入程度。
🥰来源:材料主要源于左程云算法课程进行的,每个知识点的修正和深入主要参考各平台大佬的文章,其中也可能含有少量的个人实验自证。
🤭结语:如果有帮到你的地方,就点个赞关注一下呗,谢谢🎈🎄🌷!!!
🌈【C++】秋招&实习面经汇总篇


文章目录

      • 贪心算法
      • 并查集
    • 参考博客


😊点此到文末惊喜↩︎

贪心算法

  1. 需要整理堆的使用,重写cmp
auto cmp = [&](const int& a, const int &b) {
    return cnt[a] < cnt[b];//此处cnt可由上文完成定义(最大堆--跟sort正好相反)
};
priority_queue<int, vector<int>, decltype(cmp)>pq{cmp};
  1. 分解过程
    • 分解业务
    • 根据业务逻辑找到不同的贪心策略
    • 可以举出反例的贪心策略直接跳过,不能举出反例的要证明其有效性
  2. 贪心算法的解题套路
    • 实现一个不依靠贪心策略的解法X,可以用最暴力的尝试
    • 脑补出贪心策略A、贪心策略B、贪心策略C…
    • 用解法X和对数器,用实验的方式得知哪个贪心策略正确
    • 不要去纠结贪心策略的证明
  3. 贪心策略:通常使用堆和排序
  4. 示例:排序式贪心
    • 题目:
      • 一些项目要占用一一个会议室宣讲,会议室不能同时容纳两个项目的宣讲。
      • 给你每- -个项目开始的时间和结束的时间
      • 你来安排宣讲的日程,要求会议室进行的宣讲的场次最多。
      • 返回最多的宣讲场次。
    • 贪心思路:每次优先安排结束时间最早的,并且将无法安排的进行删除
  5. 示例:堆式贪心1
    • 题目:
      • 一块金条切成两部分,需要花费和原长度一样的铜板数量
      • 比如长度为20的金条,不管怎么切,都要花费20个铜板。
      • 一群人各自分到自己想要的金条部分(和为总长度),怎么分最省铜板?
    • 思路1:每次尽可能的切下最大的部分
    • 思路2:使用哈夫曼树,每次弹出最小的两个数合并后在压入
      在这里插入图片描述
  6. 示例:堆式贪心2
    • 题目:
      • 输入:正数数组costs、正数数组profits、 正数K、正数M。costs[]表示i号项目的花费,profits[]表示i号项目在扣除花费之后还能挣到的钱(利润)
      • K表示你只能串行的最多做k个项目,M表示你初始的资金
      • 说明:每做完一个项目,马上获得的收益,可以支持你去做下一个项目。不能并行的做项目。
      • 输出:你最后获得的最大钱数。
    • 思路1:建立两个堆,一个以costs作为key的小根堆,一个是以profits作为key的大根堆。
    struct Program {
    	int p;
    	int c
    	Program(int profit, int cost) : p(profit), c(cost){}
    }
    
    int FindMaxProfits(vector<int> profits, vector<int> costs, int times, int surplus) {
    	// 比较最小花费
    	auto cmp_min_cost = [](const Program &a, const Program &b)->bool{
    		return a.c < b.c;
    	};
    	// 比较最大利润
    	auto cmp_max_profit = [](const Program &a, const Program &b)->bool{
    		return a.p > b.p;
    	};
    	// 关于花费的小根堆
    	priority_queue<Program , vector<Program>, decltype(cmp_min_cost)> min_cost_pq;
    	// 关于利润的大根堆
    	priority_queue<Program , vector<Program>, decltype(cmp_max_profit)> max_profit_pq;
    	// 将所有花费压入优先队列中
    	for (int i = 0; i < profits.size(); ++i) {
    		Program pg = {profits[i], costs[i]};
    		min_cost_pq.push(pg);
    	}	
    	// 每次循环取出所有可支持的项目,并压入最大利润队列
    	for (int i = 0; i < times; ++i) {
    		while (!min_cost_pq.empty() && min_cost_pq.top().c <= surplus){
    			Program pg = min_cost_pq.top();
    			min_cost_pq.pop();
    			max_profit_pq.push(pg);
    		}
    		// 如果最大利润队列为空,说明没有符合的项目可以继续进行
    		if (max_profit_pq.empty()) {
    			return surplus;
    		}
    		// 获取最大利润
    		surplus += max_profit_pq.top().p;
    		max_profit_pq.pop();
    	}	
    
    }
    

并查集

  1. 基本操作
    • 并:合并两个子集为一个新的集合
    • 查:通过查找一个结点的根节点,从而查找元素所属子集
  2. 作用:快速确定集合中的两两元素是否属于S的同一子集
  3. 基本并查集
    • 问题:每一次Find操作的时间复杂度为O(H),H为树的高度,由于树的不断合并可能会使树严重不平衡,最坏情况每个节点都只有一个子节点,如下图3(第一个点为根节点)在这里插入图片描述
    #include <vector>
    class DisjSet {
    private:
    	vector<int> parent; 
    public:
    	DisjSet(int max_size) : parent(vector<int>(max_size)) {
    		// 各自为营:初始化每一个元素的根节点都为自身
    		for(int i = 0; i < max_size; i++) 
    			parent[i] = i; 
    	}
    	// 查找:没找到就一直递归查看父亲结点
    	int find(int x) {
    		return (parent[i] == x ? x : find(parent[i]);
    	}
    	// 合并:将 x1 所在的集合的根节点的父节点设置为 x2 所在集合的根节点
    	void to_union(int x1, int x2) {
            parent[find(x1)] = find(x2);
        }
    	// 判断两个元素是否属于同一个集合
        bool is_same(int e1, int e2) {
            return find(e1) == find(e2);
        }
    };
    
    
  4. 优化并查集
    • 路径压缩:查询过程中,将沿途每个结点的父结点都设置为根结点,下次就可以减少查询路径长度
    • 按秩合并:“按秩合并”。实际上就是在合并两棵树时,将高度较小的树合并到高度较大的树上。这里我们使用“秩”(rank)代替高度,秩表示高度的上界,通常情况我们令只有一个节点的树的秩为0,严格来说,rank + 1才是高度的上界;两棵秩分别为r1、r2的树合并,如果秩不相等,我们将秩小的树合并到秩大的树上,这样就能保证新树秩不大于原来的任意一棵树。如果r1与r2相等,两棵树任意合并,并令新树的秩为r1 + 1。
    #include <vector>
    class DisjSet {
      private:
        std::vector<int> parent;
        std::vector<int> rank; // 秩
      public:
        DisjSet(int max_size) : parent(std::vector<int>(max_size)),
                                rank(std::vector<int>(max_size, 0)) {
            for (int i = 0; i < max_size; ++i)
                parent[i] = i;
        }
        int find(int x) {
            return x == parent[x] ? x : (parent[x] = find(parent[x]));
        }
        void to_union(int x1, int x2) {
            int f1 = find(x1);
            int f2 = find(x2);
            if (rank[f1] > rank[f2])
                parent[f2] = f1;
            else {
                parent[f1] = f2;
                if (rank[f1] == rank[f2])
                    ++rank[f2];
            }
        }
        bool is_same(int e1, int e2) {
            return find(e1) == find(e2);
        }
    };
    


少年,我观你骨骼清奇,颖悟绝伦,必成人中龙凤。
不如点赞·收藏·关注一波

🚩点此跳转到首行↩︎

参考博客

  1. 知乎并查集
  2. 待定引用
  3. 待定引用
  4. 待定引用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1218221.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

text/xml和application/xml

困惑 在http消息中&#xff0c;同样是传送xml信息&#xff0c;有的时候看到Content-Type的值是text/xml&#xff0c;有的时候值是application/xml&#xff0c;感到困惑。 例如&#xff0c;用Postman发送http消息给Tomcat中的基于JAX-WS的 web服务&#xff1a; 请求中传送了xm…

快速搭建本地的chatgpt

快速搭建本地的chatgpt 参考&#xff1a;一篇文章教你使用Docker本地化部署Chatgpt&#xff08;非api&#xff0c;速度非常快&#xff01;&#xff01;&#xff01;&#xff09;及裸连GPT的方式&#xff08;告别镜像GPT&#xff09;-CSDN博客 前提是linux下 已安装docker 命…

系列五、JVM的内存结构【PC寄存器】

一、位置 CPU中 二、作用 每个线程都有一个程序计数器&#xff0c;是线程私有的&#xff0c;所谓PC寄存器其实就是一个指针&#xff0c;指向方法区中的方法字节码&#xff08;用来存储指向下一条指令的地址&#xff0c;也即将要执行的指令代码&#xff09;&#xff0c;由执行引…

反向运算放大器

在学习模拟电路的时候&#xff0c;学习到运算放大器&#xff0c;但实际印象并不深刻&#xff0c;在此进行二次知识整理&#xff0c;以加深深度&#xff0c;下面是我个人对该器件的理解&#xff0c;其他知识暂时不深究&#xff0c;只说一下怎么用。 1、反向运算放大器干什么的&…

Python集成学习和随机森林算法

大家好&#xff0c;机器学习模型已经成为多个行业决策过程中的重要组成部分&#xff0c;然而在处理嘈杂或多样化的数据集时&#xff0c;它们往往会遇到困难&#xff0c;这就是集成学习&#xff08;Ensemble Learning&#xff09;发挥作用的地方。 本文将揭示集成学习的奥秘&am…

Docker(镜像、容器、仓库)工具安装使用命令行选项及构建、共享和运行容器化应用程序

文章目录 前言&#x1f31f;一、Docker工具安装&#x1f31f;二、Docker命令行选项&#x1f30f;2.1.docker run命令选项&#xff1a;&#x1f30f;2.2.docker build命令选项&#xff1a;&#x1f30f;2.3.docker images命令选项&#xff1a;&#x1f30f;2.4.docker ps命令选项…

CTF-PWN-堆-【前置知识】

CTF-PWN-堆 堆申请堆块main_areanabrk&sbrk函数mallocfreefree后top chunk 堆 由malloc alloc realloc 函数分配 chunk的前指的是地址低的&#xff0c;chunk的高指的是地址高的 申请堆块 ptmalloc2堆管理器&#xff1a; 通俗的讲就是相当于一个”中间商”&#xff0c;在…

实用篇-ES-RestClient查询文档

一、快速入门 上面的查询文档都是依赖kibana&#xff0c;在浏览器页面使用DSL语句去查询es&#xff0c;如何用java去查询es里面的文档(数据)呢 我们通过match_all查询来演示基本的API&#xff0c;注意下面演示的是 match_all查询&#xff0c;也叫基础查询 首先保证你已经做好了…

Linux_系统信息_uname查看内核版本、内核建立时间、处理器类型、顺便得到操作系统位数等

1、uname --help 使用uname --help查看uname命令的帮助信息 2、uname -a 通过上面的help就知道-a选项显示全部内容时的含义了。 内核名是Linux主机名是lubancat&#xff0c;如果想看主机名可以使用命令hostname&#xff1b;内核版本是Linux 4.19.232&#xff0c;建立时间为2…

解锁编程潜能:探索亚马逊CodeWhisperer,打造编程世界的声音引导者

文章目录 前言一、什么是 Amazon CodeWhisperer&#xff1f;二、如何使用CodeWhisperer&#xff1f;安装CodeWhisperer插件配置CodeWhisperer生成注释和文档 总结 前言 随着CHATGPT的一声巨响&#xff0c;大语言模型已经成为了一个备受瞩目的创新应用。亚马逊云科技作为全球领…

V10 桌面版、服务器版系统加固

V10 桌面版、服务器版系统加固 一、 文档说明 本文档中涉及的加固方法主要包括&#xff1a;密码策略配置、防火墙规 则配置、禁用高风险服务等。 二、 V10 桌面版系统加固 2.1 密码策略配置 密码策略包括密码老化控制策略和密码复杂度策略。密码老化 控制策略需要配置/etc…

Power Automate-当收到HTTP请求时触发流程

选择创建自动化云端流&#xff0c;点跳过 第一个操作搜索HTTP&#xff0c;点击当收到HTTP请求时 点击使用示例有效负载生成架构 写入JSON&#xff0c;点击完成 正文JSON架构就自动生成了&#xff0c;再点击左下角的显示高级选项 Method根据需求选择 可以选择JSON中的参数赋值给…

网络安全(黑客技术)—高效自学

前言 前几天发布了一篇 网络安全&#xff08;黑客&#xff09;自学 没想到收到了许多人的私信想要学习网安黑客技术&#xff01;却不知道从哪里开始学起&#xff01;怎么学 今天给大家分享一下&#xff0c;很多人上来就说想学习黑客&#xff0c;但是连方向都没搞清楚就开始学习…

【ARM Trace32(劳特巴赫) 使用介绍 2.1 -- TRACE32 Practice 脚本 cmm 脚本学习】

请阅读【ARM Coresight SoC-400/SoC-600 专栏导读】 上篇文章【ARM Trace32(劳特巴赫) 使用介绍 2 - Veloce 环境中使用trace32 连接 Cortex-M33】 下篇文章【ARM Trace32(劳特巴赫) 使用介绍 2.2 – TRACE32 进阶命令之 DIAG 弹框命令】 文章目录 1. TRACE32 Practice 语法1.…

【转载】快速搭建OpenGL环境!!!Windows10 + Visual Studio 2019 搭建OpenGL环境

目录 具体链接&#xff1a; 【转自】 完成后效果如下&#xff1a; 一开始的爆红&#xff1a; 下载安装后&#xff1a; 运行成功&#xff1a; 具体链接&#xff1a; 萌新向&#xff01;&#xff01;&#xff01;Windows10 Visual Studio 2019 搭建OpenGL环境&#xff08;…

StringBuffer和StringBuilder的区别与联系

文章目录 区别一览StringBuffer如何实现多线程同步关键字&#xff08;Synchronized&#xff09;性能考虑使用场景 当不使用多线程的情况下&#xff0c;是否StringBuffer和StringBuilder的性能一样&#xff1f;性能差异原因实践中的选择结论 区别一览 StringBuffer 和 StringBu…

实际使用Elasticdump工具对Elasticsearch集群进行数据备份和数据还原

文/朱季谦 目录一、Elasticdump工具介绍二、Elasticdump工具安装三、Elasticdump工具使用 最近在开发当中做了一些涉及到Elasticsearch映射结构及数据导出导入的工作&#xff0c;怕以后会把这过程忘记&#xff0c;可谓好记性不如烂笔头&#xff0c;故而记录成一篇博文。 玩El…

Jenkinsfile+Dockerfile前端vue自动化部署

前言 本篇主要介绍如何自动化部署前端vue项目 其中&#xff0c;有两种方案&#xff1a; 第一种是利用nginx进行静态资源转发&#xff1b;第二种方案是利用nodejs进行启动访问&#xff1b; 各个组件版本如下&#xff1a; Docker 最新版本&#xff1b;Jenkins 2.387.3nginx …

【项目】云备份系统基础功能实现

目录 一.项目介绍1.云备份认识2.服务端程序负责功能与功能模块划分3.客户端程序负责功能与功能模块划分4.开发环境 二.环境搭建1.gcc升级7.3版本2.安装jsoncpp库3.下载bundle数据压缩库4.下载httplib库 三.第三方库认识1.json(1)json认识(2)jsoncpp认识(3)json实现序列化(4)jso…