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

2023-11-21 07:45

本文主要是介绍【左程云算法全讲11】贪心算法 并查集,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

系列综述:
💞目的:本系列是个人整理为了秋招面试的,整理期间苛求每个知识点,平衡理解简易度与深入程度。
🥰来源:材料主要源于左程云算法课程进行的,每个知识点的修正和深入主要参考各平台大佬的文章,其中也可能含有少量的个人实验自证。
🤭结语:如果有帮到你的地方,就点个赞关注一下呗,谢谢🎈🎄🌷!!!
🌈【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 cProgram(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);}
    };
    
  5. 并查集示例
    • 题目
      • 如果两个user,a字段一样,或者b字段一样、或者c字段一样,就认为是同一个人
      • 请合并user,并返回合并后的人数
struct User {string a;string b;string c;User(string a1, string b1, string c1) : a(a1), b(b1), c(c1){} 
};


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

🚩点此跳转到首行↩︎

参考博客

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

这篇关于【左程云算法全讲11】贪心算法 并查集的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/400883

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

usaco 1.3 Barn Repair(贪心)

思路:用上M块木板时有 M-1 个间隙。目标是让总间隙最大。将相邻两个有牛的牛棚之间间隔的牛棚数排序,选取最大的M-1个作为间隙,其余地方用木板盖住。 做法: 1.若,板(M) 的数目大于或等于 牛棚中有牛的数目(C),则 目测 给每个牛牛发一个板就为最小的需求~ 2.否则,先对 牛牛们的门牌号排序,然后 用一个数组 blank[ ] 记录两门牌号之间的距离,然后 用数组 an

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

秋招最新大模型算法面试,熬夜都要肝完它

💥大家在面试大模型LLM这个板块的时候,不知道面试完会不会复盘、总结,做笔记的习惯,这份大模型算法岗面试八股笔记也帮助不少人拿到过offer ✨对于面试大模型算法工程师会有一定的帮助,都附有完整答案,熬夜也要看完,祝大家一臂之力 这份《大模型算法工程师面试题》已经上传CSDN,还有完整版的大模型 AI 学习资料,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

poj 3190 优先队列+贪心

题意: 有n头牛,分别给他们挤奶的时间。 然后每头牛挤奶的时候都要在一个stall里面,并且每个stall每次只能占用一头牛。 问最少需要多少个stall,并输出每头牛所在的stall。 e.g 样例: INPUT: 51 102 43 65 84 7 OUTPUT: 412324 HINT: Explanation of the s

poj 1182 并查集 食物链类

题意: 有n只动物,分别编号1....n。所有动物都属于A,B,C中的一种,已知A吃B,B吃C,C吃A。 按顺序给出下面两种共K条信息: 1. x 和 y 属于同一类。 2. x 吃 y 。 然而这些信息可能会出错,有可能有的信息和之前给出的信息矛盾,也有的信息可能给出的 x 和 y 不在n的范围内。 求k条信息中有多少条是不正确的。 解析: 对于每只动物,创建3个元素 i