C++算法学习心得七.贪心算法(3)

1.根据身高重建队列(406题)

题目描述:

假设有打乱顺序的一群人站成一个队列,数组 people 表示队列中一些人的属性(不一定按顺序)。每个 people[i] = [hi, ki] 表示第 i 个人的身高为 hi ,前面 正好 有 ki 个身高大于或等于 hi 的人。

请你重新构造并返回输入数组 people 所表示的队列。返回的队列应该格式化为数组 queue ,其中 queue[j] = [hj, kj] 是队列中第 j 个人的属性(queue[0] 是排在队列前面的人)。

示例 1:

  • 输入:people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]]
  • 输出:[[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]]
  • 解释:
    • 编号为 0 的人身高为 5 ,没有身高更高或者相同的人排在他前面。
    • 编号为 1 的人身高为 7 ,没有身高更高或者相同的人排在他前面。
    • 编号为 2 的人身高为 5 ,有 2 个身高更高或者相同的人排在他前面,即编号为 0 和 1 的人。
    • 编号为 3 的人身高为 6 ,有 1 个身高更高或者相同的人排在他前面,即编号为 1 的人。
    • 编号为 4 的人身高为 4 ,有 4 个身高更高或者相同的人排在他前面,即编号为 0、1、2、3 的人。
    • 编号为 5 的人身高为 7 ,有 1 个身高更高或者相同的人排在他前面,即编号为 1 的人。
    • 因此 [[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]] 是重新构造后的队列。

贪心算法: 

有两个维度,h和k,看到这种题目一定要想如何确定一个维度,然后再按照另一个维度重新排列

按照身高h来排序呢,身高一定是从大到小排(身高相同的话则k小的站前面),让高个子在前面。

此时我们可以确定一个维度了,就是身高,前面的节点一定都比本节点高。

按照身高排序之后,优先按身高高的people的k来插入,后序插入节点也不会影响前面已经插入的节点,最终按照k的规则完成了队列

局部最优:优先按身高高的people的k来插入。插入操作过后的people满足队列属性

全局最优:最后都做完插入操作,整个队列满足题目队列属性

class Solution {
public://自定义的一个排序规则static bool cmp(const vector<int>& a,const vector<int>& b){if(a[0] == b[0])return a[1] < b[1];//如果两个值相等则可以按照来排序return a[0] > b[0];//否则按照高度大小来排序}vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {sort(people.begin(),people.end(),cmp);//排序vector<vector<int>>que;//申请一个队列//去遍历整个数组,for(int i = 0;i < people.size();i++){int postion = people[i][1];//找到k的位置que.insert(que.begin() + postion,people[i]);//去插入}return que;}
};
  • 时间复杂度:O(nlog n + n^2)
  • 空间复杂度:O(n)

使用vector(动态数组)来insert,是费时的,插入再拷贝的话,单纯一个插入的操作就是O(n^2)了,甚至可能拷贝好几次,就不止O(n^2)了。

改成链表之后

class Solution {
public:// 身高从大到小排(身高相同k小的站前面)static bool cmp(const vector<int>& a, const vector<int>& b) {if (a[0] == b[0]) return a[1] < b[1];return a[0] > b[0];}vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {sort (people.begin(), people.end(), cmp);list<vector<int>> que; // list底层是链表实现,插入效率比vector高的多for (int i = 0; i < people.size(); i++) {int position = people[i][1]; // 插入到下标为position的位置std::list<vector<int>>::iterator it = que.begin();while (position--) { // 寻找在插入位置it++;}que.insert(it, people[i]);}return vector<vector<int>>(que.begin(), que.end());}
};
  • 时间复杂度:O(nlog n + n^2)
  • 空间复杂度:O(n)

2.用最少数量的箭引爆气球( 452题)

题目描述:

在二维空间中有许多球形的气球。对于每个气球,提供的输入是水平方向上,气球直径的开始和结束坐标。由于它是水平的,所以纵坐标并不重要,因此只要知道开始和结束的横坐标就足够了。开始坐标总是小于结束坐标。

一支弓箭可以沿着 x 轴从不同点完全垂直地射出。在坐标 x 处射出一支箭,若有一个气球的直径的开始和结束坐标为 xstart,xend, 且满足  xstart ≤ x ≤ xend,则该气球会被引爆。可以射出的弓箭的数量没有限制。 弓箭一旦被射出之后,可以无限地前进。我们想找到使得所有气球全部被引爆,所需的弓箭的最小数量。

给你一个数组 points ,其中 points [i] = [xstart,xend] ,返回引爆所有气球所必须射出的最小弓箭数。

示例 1:

  • 输入:points = [[10,16],[2,8],[1,6],[7,12]]
  • 输出:2
  • 解释:对于该样例,x = 6 可以射爆 [2,8],[1,6] 两个气球,以及 x = 11 射爆另外两个气球

贪心算法: 为了让气球尽可能的重叠,需要对数组进行排序,如果气球重叠了,重叠气球中右边边界的最小值 之前的区间一定需要一个弓箭。注意=也可以射中气球,

class Solution {
static bool cmp(const vector<int>& a,const vector<int>& b){return a[0] < b[0];//自定义的一个排序规则
}
public:int findMinArrowShots(vector<vector<int>>& points) {if(points.size() == 0)return 0;//如果没有气球返回0sort(points.begin(),points.end(),cmp);//按照定义规则排序int result = 1;//最开始默认一支箭//我们从头开始遍历for(int i = 1;i < points.size();i++){if(points[i][0] > points[i-1][1]){result++;//当前的左边界大于上一个右边界,此时+1}else{points[i][1] = min(points[i-1][1],points[i][1]);//否则更新边界,右边界,取前一个和现在右边界最小值}}return result;}
};
  • 时间复杂度:O(nlog n),因为有一个快排
  • 空间复杂度:O(1)

 3.无重叠区间(435题)

题目描述:

给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。

注意: 可以认为区间的终点总是大于它的起点。 区间 [1,2] 和 [2,3] 的边界相互“接触”,但没有相互重叠。

示例 1:

  • 输入: [ [1,2], [2,3], [3,4], [1,3] ]
  • 输出: 1
  • 解释: 移除 [1,3] 后,剩下的区间没有重叠。

贪心算法:和上一题类似 ,我来按照左边界排序,从左向右记录非交叉区间的个数。最后用区间总数减去非交叉区间的个数就是需要移除的区间个数了。要求非交叉区间的最大个数

class Solution {
static bool cmp(const vector<int>& a,const vector<int>& b){return a[0] < b[0];//自定义规则
}
public:int eraseOverlapIntervals(vector<vector<int>>& intervals) {if(intervals.size() == 0)return 0;sort(intervals.begin(),intervals.end(),cmp);//排序int count = 0;for(int i = 1;i < intervals.size();i++){//如果当前的左边界小于前一个右边界if(intervals[i][0] < intervals[i-1][1]){count++;//计数intervals[i][1] = min(intervals[i][1],intervals[i-1][1]);//更新当前右边界}}return count;}
};
  • 时间复杂度:O(nlog n) ,有一个快排
  • 空间复杂度:O(n),有一个快排,最差情况(倒序)时,需要n次递归调用。因此确实需要O(n)的栈空间

 4.划分字母区间(763题)

题目描述:

字符串 S 由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。返回一个表示每个字符串片段的长度的列表。

示例:

  • 输入:S = "ababcbacadefegdehijhklij"
  • 输出:[9,7,8] 解释: 划分结果为 "ababcbaca", "defegde", "hijhklij"。 每个字母最多出现在一个片段中。 像 "ababcbacadefegde", "hijhklij" 的划分是错误的,因为划分的片段数较少。

贪心算法:

在遍历的过程中相当于是要找每一个字母的边界,如果找到之前遍历过的所有字母的最远边界,说明这个边界就是分割点了。此时前面出现过所有字母,最远也就到这个边界了。

可以分为如下两步:

  • 统计每一个字符最后出现的位置
  • 从头遍历字符,并更新字符的最远出现下标,如果找到字符最远出现位置下标和当前下标相等了,则找到了分割点
class Solution {
public:vector<int> partitionLabels(string s) {int hash[27] = {0};//定义一个数组来规定界限for (int i = 0; i < s.size(); i++) {hash[s[i] - 'a'] = i;//对每一个元素进行记录最远的出现位置,这里i可以覆盖之前出现过的元素}vector<int> result;int left = 0, right = 0;//左和右边界//遍历for (int i = 0; i < s.size(); i++) {right = max(right, hash[s[i] - 'a']);//更新右边最大的边界if (right == i) {result.push_back(right - left + 1);//如果右边边界等于到了当前下标就把数组长度加入结果left = i + 1;//更新左边界}}return result;}
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(1),使用的hash数组是固定大小

5.合并区间(56题)

题目描述:

给出一个区间的集合,请合并所有重叠的区间。

示例 1:

  • 输入: intervals = [[1,3],[2,6],[8,10],[15,18]]
  • 输出: [[1,6],[8,10],[15,18]]
  • 解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].

 贪心算法:判断区间重叠,区别就是判断区间重叠后的逻辑,本题是判断区间重贴后要进行区间合并,

所以一样的套路,先排序,让所有的相邻区间尽可能的重叠在一起,按左边界,或者右边界排序都可以,处理逻辑稍有不同。

按照左边界从小到大排序之后,如果 intervals[i][0] <= intervals[i - 1][1] 即intervals[i]的左边界 <= intervals[i - 1]的右边界,则一定有重叠。(本题相邻区间也算重贴,所以是<=)

其实就是用合并区间后左边界和右边界,作为一个新的区间,加入到result数组里就可以了。如果没有合并就把原区间加入到result数组。

class Solution {
static bool cmp(const vector<int>& a,const vector<int>& b){return a[0] < b[0];//自定义排序规则
}
public:vector<vector<int>> merge(vector<vector<int>>& intervals) {vector<vector<int>>result;sort(intervals.begin(),intervals.end(),cmp);//排序result.push_back(intervals[0]);//我们定义一个数组,首先将第一个集合加入进去//注意i的取值范围需要从1开始取值,然后遍历整个数组for(int i = 1;i < intervals.size();i++){//这里数组的最后一个元素的右边界大于下一个元素的左边界说明有重叠部分,需要更新下一个元素的右边界if(intervals[i][0] <= result.back()[1]){result.back()[1] = max(result.back()[1],intervals[i][1]);//这里需要更新右边界的最大值,}else{result.push_back(intervals[i]);//如果没有重复将数组加入到结果集中}}return result;}
};
  • 时间复杂度: O(nlogn)
  • 空间复杂度: O(logn),排序需要的空间开销

6. 单调递增的数字(738题)

题目描述:

给定一个非负整数 N,找出小于或等于 N 的最大的整数,同时这个整数需要满足其各个位数上的数字是单调递增。

(当且仅当每个相邻位数上的数字 x 和 y 满足 x <= y 时,我们称这个整数是单调递增的。)

示例 1:

  • 输入: N = 10
  • 输出: 9

贪心算法:例如:98,一旦出现strNum[i - 1] > strNum[i]的情况(非单调递增),首先想让strNum[i - 1]--,然后strNum[i]给为9,这样这个整数就是89,即小于98的最大的单调递增整数。本题需要从后向前遍历

class Solution {
public:int monotoneIncreasingDigits(int n) {string strnum = to_string(n);//首先对证书取字符串操作,int flag = strnum.size();//设置标志位,再最末尾//从后向前遍历,可以对数据进行操作,更方便for(int i = strnum.size() - 1;i > 0;i--){//如果相当于前一个数据大于后一个数据进行操作if(strnum[i-1] > strnum[i]){flag = i;//记录标志位strnum[i-1]--;//并且对其前一个进行-1操作}}for(int i = flag;i < strnum.size();i++){strnum[i] = '9';//我们需要把标志位后面的所有位变成9}return stoi(strnum);//最后返回将字符串变成整数}
};
  • 时间复杂度:O(n),n 为数字长度
  • 空间复杂度:O(n),需要一个字符串,转化为字符串操作更方便

7.监控二叉树(968题)

题目描述:

给定一个二叉树,我们在树的节点上安装摄像头。

节点上的每个摄影头都可以监视其父对象、自身及其直接子对象。

计算监控树的所有节点所需的最小摄像头数量。

​​​​​​​

贪心算法:

要从下往上看,局部最优:让叶子节点的父节点安摄像头,所用摄像头最少,整体最优:全部摄像头数量所用最少!

大体思路就是从低到上,先给叶子节点父节点放个摄像头,然后隔两个节点放一个摄像头,直至到二叉树头结点。

取了左孩子的返回值,右孩子的返回值,即left 和 right, 以后推导中间节点的状态 

来看看这个状态应该如何转移,先来看看每个节点可能有几种状态:

有如下三种:

  • 该节点无覆盖
  • 本节点有摄像头
  • 本节点有覆盖

我们分别有三个数字来表示:

  • 0:该节点无覆盖
  • 1:本节点有摄像头
  • 2:本节点有覆盖

空节点的状态只能是有覆盖,这样就可以在叶子节点的父节点放摄像头了 

  • 情况1:左右节点都有覆盖

左孩子有覆盖,右孩子有覆盖,那么此时中间节点应该就是无覆盖的状态了

  • 情况2:左右节点至少有一个无覆盖的情况

如果是以下情况,则中间节点(父节点)应该放摄像头

  • 情况3:左右节点至少有一个有摄像头

如果是以下情况,其实就是 左右孩子节点有一个有摄像头了,那么其父节点就应该是2(覆盖的状态)

  • 情况4:头结点没有覆盖

以上都处理完了,递归结束之后,可能头结点 还有一个无覆盖的情况,递归结束之后,还要判断根节点,如果没有覆盖,result++,

class Solution {
private:int result = 0;int traversal(TreeNode* cur){if(cur == NULL)return 2;// 空节点,该节点有覆盖int left = traversal(cur->left);//左int right = traversal(cur->right);//右// 情况1// 左右节点都有覆盖if(left == 2 && right == 2)return 0;// 情况2// left == 0 && right == 0 左右节点无覆盖// left == 1 && right == 0 左节点有摄像头,右节点无覆盖// left == 0 && right == 1 左节点有无覆盖,右节点摄像头// left == 0 && right == 2 左节点无覆盖,右节点覆盖// left == 2 && right == 0 左节点覆盖,右节点无覆盖if(left == 0 || right == 0){result++;return 1;}// 情况3// left == 1 && right == 2 左节点有摄像头,右节点有覆盖// left == 2 && right == 1 左节点有覆盖,右节点有摄像头// left == 1 && right == 1 左右节点都有摄像头// 其他情况前段代码均已覆盖if(left == 1 || right == 1)return 2;return -1;}
public:int minCameraCover(TreeNode* root) {result = 0;// root 无覆盖if(traversal(root) == 0){result++;}return result;}
};
  • 时间复杂度: O(n),需要遍历二叉树上的每个节点
  • 空间复杂度: O(n)

总结: 

根据身高重建队列:两个维度,一个是身高维度,另一个是前面几个人维度,我们需要先确定一个维度,然后再去确定另一个维度,首先根据身高来进行排序,由大到小排列,如果相同身高的话k小的排列,然后我们根据k来排序,申请一个队列,然后找到该插入的位置,进行Insert操作,更好的方法是使用链表的底层队列实现

用最少数量的箭引爆气球:为了让气球尽可能的重叠,需要对数组进行排序,如果气球重叠了,重叠气球中右边边界的最小值 之前的区间一定需要一个弓箭。注意=也可以射中气球,这样就可以实现,记得更新右边界值

无重叠区间:和上面一样首先根据左边界进行排序,当前左边界小于前一个右边界,更新右边界,需要去除的区间+1,找上述两个值的最小值即可更新右边界。

划分字母区间:在遍历过程中,记录最远下标,hash[s[i] - 'a'] = i这个是定义一个数组来实现,i是下标,每次更新下标最远处,设置两个边界,left,right,满足右边界等于i 时候记录一个区间,再更新左边界

合并区间:贪心算法,先排序,按照左边界右边界排序都可,按照左边界排序,如果当前左边界小于前一个的右边界,说明有重叠区间,首先自定义一个排序规则,对数组排序,然后定义结果集,首先加入一个集合进去,开始遍历,如果出现了上述情况,更新右边界最大值,否则加入结果集数组

单调递增的数字:根据题意遇到前一个数字大于后一个数字情况,这时候需要改变后面的数字,把当前数字减1,后面数字都变为9,首先需要把数字按照字符串进行处理,我们需要从后向前遍历,设置一个标志位,该标志位在末尾,如果当前数字小于前一个数字,就进行记录,并且减一,然后再从该标志位到末尾全部变为9即可,注意最后需要把字符串形式转换成整数

监控二叉树:要从下往上看,局部最优:让叶子节点的父节点安摄像头,所用摄像头最少,整体最优:全部摄像头数量所用最少,大体思路就是从低到上,先给叶子节点父节点放个摄像头,然后隔两个节点放一个摄像头,直至到二叉树头结点,知道每个节点状态,分别用数字代表状态,根据不同情况,根据叶子节点不同状态返回状态。

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

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

相关文章

微服务入门篇:Ribbon负载均衡(原理,均衡策略,饥饿加载)

目录 1.负载均衡原理2.负载均衡策略3.饥饿加载 1.负载均衡原理 在使用 LoadBalanced 注解后&#xff0c;Spring Cloud Ribbon 将会为 RestTemplate 添加负载均衡的能力。 负载均衡的流程如下&#xff1a; 当使用 RestTemplate 发送请求时&#xff0c;会先判断请求的 URL 是否包…

双目相机立体匹配基础

双目匹配就是用左相机和右相机去拍摄同一个点&#xff0c;目的是找到三维世界的同一个点&#xff0c;也就是在左相机和右相机中的成像点之间的像素差&#xff08;视差&#xff09;&#xff0c;根据视差去求解深度&#xff0c;那么找到左相机点到右相机的同一个对应点这个过程就…

c++设计模式之观察者模式(发布-订阅模式)

介绍 观察者模式主要关注于对象的一对多关系&#xff0c;其中多个对象都依赖于一个对象&#xff0c;当该对象的状态发生改变时&#xff0c;其余对象都能接收到相应的通知。 如&#xff0c;现在有 一个数据对象三个画图对象&#xff0c;分别wield曲线图、柱状图、饼状图三个对象…

数据结构与算法面试系列-03

1. 一球从100米高度自由落下,每次落地后反跳回原高度的一半;再落下,求它在 第10次落地时,共经过多少米?第10次反弹多高? 程序代码 package com.jingxuan.system;public class Sphere {public static void main(String[] args) {double s = 0;double t = 100;for (int i…

Qt6入门教程 15:QRadioButton

目录 一.简介 二.常用接口 三.实战演练 1.径向渐变 2.QSS贴图 3.开关效果 4.非互斥 一.简介 QRadioButton控件提供了一个带有文本标签的单选按钮。 QRadioButton是一个可以切换选中&#xff08;checked&#xff09;或未选中&#xff08;unchecked&#xff09;状态的选项…

Flink 1.18.1的基本使用

系统示例应用 /usr/local/flink-1.18.1/bin/flink run /usr/local/flies/streaming/SocketWindowWordCount.jar --port 9010nc -l 9010 asd asd sdfsf sdf sdfsdagd sdf单次统计示例工程 cd C:\Dev\IdeaProjectsmvn archetype:generate -DarchetypeGroupIdorg.apache.flink -…

maven代码规范检查(checkstyle、findbugs)

maven代码规范检查 前言一、使用checkstyle插件1. maven-checkstyle-plugin 介绍2. 接入方式3. 如何排除某个类、包下面的文件不进行检查使用suppressionsLocation 4. 如何关闭 二、使用findbugs插件1.findbugs-maven-plugin介绍2. 接入方式3. 如何排除某个类、包下面的文件不进…

TraceRoute 跟踪路由工具

随着企业网络需求的不断增长&#xff0c;组织发现监控和管理其网络基础设施变得越来越困难&#xff0c;网络管理员正在转向其他工具和资源&#xff0c;这些工具和资源可以使他们的工作更轻松一些&#xff0c;尤其是在故障排除方面。 目前&#xff0c;网络管理员主要使用简单、…

git使用以及工作中开发流程

Git是当前最先进、最主流的分布式版本控制系统&#xff0c;免费、开源。 主要概念&#xff1a; 基本流程&#xff1a; 命令&#xff1a; git commit -a # 省略了add到暂存区的步骤&#xff0c;直接提交工作区的修改内容到版本库&#xff0c;不包括新增的文件。git fetc…

myql 项目数据库和表的设计

1.表的设计和创建 2.在navicate运行这些代码 create table user(id int not null auto_increment primary key,name varchar(50) not null unique,password varchar(50) not null,state enum(online,offline) default offline ); create table friend(userid int not null,…

day37WEB攻防-通用漏洞XSS跨站权限维持钓鱼捆绑浏览器漏洞

目录 XSS-后台植入 Cookie&表单劫持&#xff08;权限维持&#xff09; 案例演示 XSS-Flash 钓鱼配合 MSF 捆绑上线 1、生成后门 2、下载官方文件-保证安装正常 3、压缩捆绑文件-解压提取运行 4、MSF 配置监听状态 5、诱使受害者访问 URL-语言要适当 XSS-浏览器网马…

Echars3D 饼图开发

关于vue echart3D 饼图开发 首先要先下载 "echarts-gl", 放在main.js npm install echarts-gl --save <template><div class"cointan"><!-- 3d环形图 --><div class"chart" id"cityGreenLand-charts"><…

03. 【Linux教程】安装虚拟机

前面小节介绍了 Linux 和 GUN 项目&#xff0c;本小节开始学习如何在 Windows 上安装虚拟机&#xff0c;虚拟机安装之后可以在虚拟机中安装 Linux 相关的操作系统&#xff0c;常见的虚拟机软件有 VirtualBox、VMware 等等&#xff0c;本教程使用 VMware 虚拟机软件来演示如何安…

java数据结构与算法刷题-----LeetCode198. 打家劫舍

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 很多人觉得动态规划很难&#xff0c;但它就是固定套路而已。其实动态规划只…

Flink CDC 3.0 详解

一、Flink CDC 概述 Flink CDC 是基于数据库日志 CDC&#xff08;Change Data Capture&#xff09;技术的实时数据集成框架&#xff0c;支持全增量一体化、无锁读取、并行读取、表结构变更自动同步、分布式架构等高级特性。配合Flink 优秀的管道能力和丰富的上下游生态&#x…

开启Android学习之旅-1

最近在学习《第一行代码 Android》&#xff0c;两天看书把所有代码都敲了一遍。由于之前没有接触过 Kotlin&#xff0c;导致了囫囵吞枣&#xff0c;跟着书会敲&#xff0c;离开就忘了。Android 大佬开发的各种框架、控件好像大部分都用了 Kotlin。看他们的源码&#xff0c;理解…

【每日一题】7.LeetCode——合并两个有序链表

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》|《数据结构与算法》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更新的动力❤️ &#x1f64f;小杨水平有限&#xff0c;欢…

【issue-YOLO】自定义数据集训练YOLO-v7 Segmentation

1. 拉取代码创建环境 执行nvidia-smi验证cuda环境是否可用&#xff1b;拉取官方代码&#xff1b; clone官方代码仓库 git clone https://github.com/WongKinYiu/yolov7&#xff1b;从main分支切换到u7分支 cd yolov7 && git checkout 44f30af0daccb1a3baecc5d80eae229…

C++——日期类

前言&#xff1a;哈喽小伙伴们&#xff0c;在上一篇文章中我们对C类与对象的前半段知识进行了简单的分享&#xff0c;其中比较重要的莫过于C类的六个默认成员函数。 所以这篇文章&#xff0c;我们通过实现一个完整的日期的操作&#xff0c;来对这些成员函数有一个更加深入的理…

RabbitMQ-高级篇

服务异步通信-高级篇 消息队列在使用过程中&#xff0c;面临着很多实际问题需要思考&#xff1a; 1.消息可靠性 消息从发送&#xff0c;到消费者接收&#xff0c;会经理多个过程&#xff1a; 其中的每一步都可能导致消息丢失&#xff0c;常见的丢失原因包括&#xff1a; 发送…