自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(104)
  • 收藏
  • 关注

原创 160相交链表

假设遍历A链表的指针名为a,遍历B链表的指针名为b:那么我们只需要让a和b先遍历完链表,如果遇到最后一个节点,就跳回到对方链表的开头即可,相当于走一遍对方走过的路程,这样只要链表有相交的地方,就必然会在相交的位置相遇。输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,6,1,8,4,5]。

2025-11-26 11:48:28 578

原创 1两数之和

我们可以通过哈希表,遍历x的时候,查找哈希表中是否存在target-x即可。也就是说,我们不能向后看,因为还没有遍历到,但是可以回头看,看x左侧是否存在target-x。在遍历到x时,从x后面开始寻找target-x,之所以要从后面找,是因为x前面的元素必然已经和x匹配过。解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1]。输入:nums = [2,7,11,15], target = 9。输入:nums = [3,2,4], target = 6。,请你在该数组中找出。

2025-11-25 09:18:26 293

原创 WebServer06

而参数需要的是裸指针,且对象还是自动管理的,局部智能指针超出作用域后还是会自动delete对象。可见,release()是永久交出对象控制权,让对象脱离智能指针管理。重复执行大括号里的内容100次,相当于你手动打开了100个终端,每个终端都执行一次连接服务器+发数据的操作。每个循环末尾的&:让这个连接在后台运行,不阻塞下一个连接的创建,这使得100个连接瞬间同时建立,而不是排队。如果不是,就看该事件关心的是读事件还是写事件,分别进行处理即可。是线程不安全的,因为它使用的是静态缓冲区,多线程调用会覆盖结果。

2025-11-18 21:03:28 610

原创 设置共享文件夹

在Windows主机中创建文件夹SharedFolder,作为共享文件夹。并在VMWare界面上方的”虚拟机“ -> ”设置“ -> "选项"中找到共享文件夹,填入这个SharedFolder的路径,选择总是启用。如果你前面没有设置uid和gid,在这里正常写入uid和gid即可。文件夹与主机中的SharedFolder文件夹就是互通的了。如果什么都没有输出,那说明配置无错误。

2025-11-14 23:58:12 208

原创 WebServer05

符号,这是因为新开的客户端与服务端完成三次握手后放入了已完成连接队列中,但accept没有放在循环里,因此服务端只会从已完成连接队列中取出一次连接,后面即使有新的连接也取不出来了。客户端回复ACK,三次握手完成,内核将这个全连接从未完成队列移动到已完成连接队列,此时连接已就绪,等待服务端处理。如果我们再开一个终端,运行client,是可以与服务端建立连接的,但是服务端却没有显示IP客户端的IP地址,新开的客户端向服务端发送消息,服务端也接收不到。这就是arg存在的意义。的已完成连接队列中取一个就绪的连接。

2025-11-12 16:56:49 934

原创 WebServer04

它的核心优势在于:跨平台(同一个CMakeLists.txt,在Linux生成Makefile,在Mac OS生成XCode工程,在Windows生成VisualStudio工程)、简化配置(自动找源文件、自动处理依赖)、支持复杂项目(处理多目录、动态/静态库、第三方依赖)而且不同的人可能使用不同的编译选项。前者:你写的会多一点,但你看试卷复习的时候就不需要翻阅课本了。链接过程:编译器不会复制库的代码,只会在你的可执行文件中记录 “我需要用到 xxx 动态库的 xxx 函数”,相当于留了一个引用地址。

2025-11-11 23:57:22 892

原创 力扣146LRU缓存

找到对应节点之后要将其移动到最前面,那这就意味着我们需要知道第二个节点的指针,这有点麻烦,因为第二个节点可能会变化。并且,每个节点要存储key/value/next/prev,因为找到尾节点之后还要返回它的key值,这样才能从哈希表中删除。但是问题又来了:如果我们把中间的元素移到了上面,那空出来的位置要补上,这就意味着必然要进行移动操作,那时间复杂度肯定不是O(n)了。因为在链表中删除元素是O(1)操作,不涉及补位,也没有预分配空间的问题。// 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}

2025-11-04 11:05:19 938

原创 上传项目至Github与从Github克隆项目

生成token:点击头像 -> Settings -> Developer Settings -> Personal access tokens -> Tokens(classic) -> Generate new token -> Generate new token(classic)推送时要求我们输入账号密码,但现在Github使用的是personal access token而不是账号密码。然后把你需要上传的文件移动/复制到这个克隆下来的文件夹里,cmd中使用copy或remove。

2025-10-31 15:22:17 357

原创 select/poll/epoll

epoll_wait。

2025-10-29 23:52:08 1041

原创 WebServer 03

我们回到WebServer,继续看Config类中的parse_arg函数(命令行参数解析器)。我们先理解一下这个getopt函数做了什么。getopt函数是Linux/Unix系统中用来解析命令行参数的标准库函数。argc和argv就不再赘述了,在01中学习过。opstring的格式规则:单个字母表示选项,后面跟冒号表示需要参数"abc" //-a,-b,-c选项都不需要参数"a:b:c:" //-a,-b,-c选项都需要参数"ab:c" //-a和-c不需要参数。

2025-10-21 00:27:10 848

原创 437路径总和III(dfs+前缀和)

当我们搜索到节点node时,计算出其前缀和为curr,我们希望在根节点root到node之间,存在这么一个节点node1,使得node1到node的和为target,那么这就意味着node1的前缀和为curr-target.为了记录数量,我们使用哈希表。输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22。输入:root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8。

2025-10-17 23:33:39 392

原创 2333贪心

从最后一个元素开始,change=1,因此消耗1个单位,让差值为3的那个对子变成差值为2,因此gap[2]要加一,gap[3]要减一,k也要减一。输入:nums1 = [1,2,3,4], nums2 = [2,10,20,19], k1 = 0, k2 = 0。输入:nums1 = [1,4,10,12], nums2 = [5,8,6,9], k1 = 1, k2 = 1。解释:假设差值分别为[1,2,2,3]且k=4,那么gap[1]=1,gap[2]=2,gap[3]=1.

2025-10-15 10:07:12 323

原创 反转链表及其应用(力扣2130)

是因为每一个对子(prev,curr)的函数都返回的是下一个对子(curr,tmp)的函数的返回值,也就是说,func(A,B)返回值依赖func(B,C),func(B,C)返回值依赖func(C,D),最终的返回值就是func(D,nullptr),也就是新链表的头节点。对于A->B->C来说,调整为A<-B->C后,需要记录C,不然就不知道哪个节点要指向B了。找到待反转部分最左侧节点的前一个节点和最右侧节点的后一个节点,再把待反转部分单独抽出来,回到上一个问题,再调整指针指向即可。

2025-10-13 21:20:57 820

原创 WebServer 02

我们来分析一下在网络阻塞/客户端宕机情形下可能出现的一种情况:如果是两次握手:客户端发送SYN报文(seq=200),但这个SYN报文被网络阻塞了。接着客户端重新发送新的SYN报文(seq=100)。但旧的SYN报文比新的SYN报文先到达。服务端收到SYN报文后,进入ESTABLISHED状态,返回一个SYN-ACK报文(seq=400,ack=201),客户端发现ack应当为101,判断为历史连接,那么客户端发送RST报文断开连接。一段时间后,新的SYN报文才到达,这次才能正确握手。

2025-10-12 12:37:10 562

原创 01背包与完全背包

如果没有超过3,假设它的重量是2,那么对于容量为3的背包来说,放入物品2后还剩的容量为1,所以只需要看容量为1的背包从下标为0、1的物品里面取,所能得到的最大价值总和是多少就可以了。情景:有N件物品和一个容量为bagweight的背包,第i件物品的重量是weight[i],其价值为value[i],每件物品有无限个(即可以多次放入背包),求背包容纳的物品的最大价值总和。但是不要忘记了,如果amount=3,那么先2再1,和先1再2是两种不同的答案,也就是说,爬楼梯求的是排列数。而此题要求的是组合数。

2025-10-10 17:20:59 782

原创 684冗余连接(并查集)

如果不是,那么就往上找u的上一级领导father[u],之所以让father[u]=find(father[u]),是为了精简整个人事体系。即在寻根的过程中,让u的上一级领导father[u]直接成为u的最高级别领导,这样u和最高级别领导就可以直接建立联系了,不需要经过一层又一层的领导。抽象地说,之所以要删除1 - 4,是因为在将节点1和节点4连接起来之前,1和4就已经是可以相互到达的了,换言之,就是1和4已经在同一个集合中。初始化:一开始大家都没有和别人拉手,相当于自己是自己的领导,自己是自己的下属。

2025-09-30 10:07:35 797

原创 WebServer 01

比喻理解:打电话A:喂,能听到吗?(第一次握手:A要确认B是否在线以及能否听到自己的声音)B:可以听到,你听得到吗?(第二次握手:B确认了自己能听到A的声音,要确认A能否听到自己的声音)A:可以听到,开始说吧!(第三次握手:A确认了自己能听到B的声音,要让B确认自己能听到B的声音)TCP握手同理:客户端:你好,能建立连接吗?(SYN)服务器:收到,我准备好了,你呢?(SYN-ACK)客户端:我也准备好了,开始传数据吧!(ACK)这些SYN、ACK是什么?

2025-09-30 09:47:56 1073

原创 654最大二叉树

[3,2,1,6,0,5] 中的最大值是 6 ,左边部分是 [3,2,1] ,右边部分是 [0,5]。- [3,2,1] 中的最大值是 3 ,左边部分是 [] ,右边部分是 [2,1]。- [2,1] 中的最大值是 2 ,左边部分是 [] ,右边部分是 [1]。- [0,5] 中的最大值是 5 ,左边部分是 [0] ,右边部分是 []。//找到[left,right)之间的最大值,构造根节点,递归。输出:[6,3,5,null,2,0,null,null,1]//找根节点下标,以便确定分界点。

2025-09-28 08:58:39 759

原创 C++线程池学习 Day10/11/12

enqueue一个lambda表达式,其参数为单个任务的开始时间,任务复杂度(任务本身for循环的次数),并指定其返回值为long long,开始执行计算任务,记录结束时间,再返回结束时间减去开始时间的值即可。首先,它应该要知道自己处理的是普通线程池还是优化线程池的数据,所以我们需要传一个字符串类型的参数表示名字;实际上当vector需要扩容时,它并不是真的扩容,而是分配一个更大的内存块,将旧内存中的元素移动到新内存中,对新增加的元素进行默认构造,再销毁旧vector中的元素并释放内存。

2025-09-25 16:02:11 736

原创 C++线程池学习 Day09

2.所有其它队列的地址在哪?但是,补上了之后有一个严重的问题:线程抢到锁后(因为每个队列一把锁,所以竞争很小)就会进入wait,那么如果这时候enqueue没有推送任务给它(虽然enqueue是找任务队列最短的那一个线程,但是有可能有多个线程的任务队列长度都为最小值,所以依然有随机性),它就会一直阻塞在wait()处。我一开始写enqueue的时候的想法是,让线程持续判断自己的工作队列是否有任务(事实上,这已经违背了线程池的初衷,因为一直在忙等待,而不是有任务来了再被唤醒),如果有就执行,没有就窃取。

2025-09-23 09:49:32 566

原创 C++线程池学习 Day08

比喻:送快递要一个片区一个片区地送,这样就不用每次都回中央仓库拿货了。只有当它的送货小车空了,它才会和同事说:“把你片区最早要送的快递给我吧,反正你也没开始送,都得从仓库现取”。这样既帮了同事,又避免了频繁交叉派单导致的缓存乒乓而让窃取者从队首窃取,这是一种负载均衡和缓存友好地这种。因为旧任务已经冷了,在任何核心的缓存中都不存在,在哪个CPU上执行都得从主内存中加载,开销差不多,不如让空闲的核心做❓追问:为什么说频繁交叉派单导致缓存乒乓?

2025-09-21 23:15:29 938

原创 C++线程池学习 Day07

1.用std::memory_order_relaxed制造一个问题,使用gdb进行调试,接着用release-acquire修复问题2.了解std::mutex底层实现:回答三个问题:(i)std::mutex底层是怎么实现的?它用了什么内存序?(ii)除了用锁,还能怎么实现线程同步?(iii)什么时候该用relaxed?什么时候必须用seq_cst?建议跳过“使用relaxed制造一个问题”这一章节。

2025-09-21 01:29:12 990

原创 C++线程池学习 Day06

3.释放-获取模式(std::memory_order_release/acquire):你拼好了一块非常关键的中心块(释放操作),拿着这块中心块走到窗口前说:“注意,在我交出这块中心块之前,我完成的所有拼图(例如一片蓝色的天空)都是有效的!如果在多线程环境下,这是危险的。它是一个规则,让你可以精确控制原子操作周围的其它内存操作(读、写)的顺序和可见性,让你能够与编译器和CPU进行对话,告诉它们这个位置是否需要严格的顺序(seq_cst),或者这个位置的顺序无所谓,可以随便优化(relaxed)

2025-09-20 00:02:41 714

原创 C++线程池学习 Day05

学习了编译、运行C++程序、进行性能测试、使用objdump反汇编、volatile关键字

2025-09-19 02:02:16 747

原创 C++线程池学习 Day04

这样一来,我们将任务打包,在堆上开辟内存给这个std::packaged_task对象,用指针ptr去管理它,后续这个任务执行完毕后,我们可以通过ptr->get_future()获取和这个std::packaged有共享资源的std::future,这样就可以获取到结果了。因此,我们不能把这个enqueue函数的参数写死了,使用模板即可解决这个问题。现代C++中,对于模板类和小函数,一般都在头文件中定义,小函数在头文件内联,模板类是强制要在头文件中定义,因为编译器在看到模板使用的同一个地方看到模板定义。

2025-09-18 00:55:43 869

原创 C++线程池学习 Day03

注:涉及std::bind,std::packaged_task,共享指针,锁,emplace与push的比较,完美转发的深入剖析1️⃣enqueue函数如何实现?2️⃣析构函数做了什么?3️⃣整体分析:这几个函数是如何配合的?一、enqueue函数由第一天的分析,我们知道enqueue函数的功能就是将任务提交到任务队列,并且确保这个任务是一个返回值为void,参数列表为空的可调用对象。1️⃣using return_type = typename std::result_of<F(Args..

2025-09-17 00:43:09 740

原创 C++线程池学习 Day02

2️⃣lambda表达式中的[this]

2025-09-16 00:16:20 895

原创 C++线程池Day01

同步原语:std::mutex和std::condition_variable. 作用是协调工作线程和任务提交者。T::something一般会认为是一个值,所以这里要加typename告诉编译器T::type是一个类型,不是一个值。T推导为std::string,在函数f的栈上构造arg对象,临时对象std::string("hello")的内容被移动到arg.对于f(s),std::forward是没有意义的:因为已经发生了拷贝:成本最高的操作已经完成了。另外,Args是和可调用对象F绑定的参数。

2025-09-14 12:46:44 454

原创 力扣452:用最少数量的箭射爆气球(排序+贪心)

从简单情况入手:如果只有两个区间,则只要这两个区间有公共部分,就只需用一只箭可以射穿。如果现在加入第三个区间,为了方便看是否有公共部分,可以先将其按照左端点大小排序。如果第三个区间的左端点比前两个区间的公共部分的右端点要小,那么不需要增加新的箭。反之就需要增加新的箭。前两个区间公共部分的右端点就是这两个区间右端点的最小值。只需遍历每个区间,看这个区间的左端点比前面所有区间的公共部分的右端点(即最小右端点)大或者小即可。同时维护公共部分的右端点。

2025-08-29 23:20:46 204

原创 动态规划:不同的二叉搜索树

其中i为根节点的二叉搜索树数量为:dp[i-1]dp[n-i]那么,1为根节点的二叉搜索树的数量为:dp[0]有三个节点的二叉搜索树有几种?dp[i]表示:i个节点组成二叉搜索树的个数。1为根节点:左子树0个节点,右子树2个节点。2为根节点:左子树1个节点,右子树1个节点。3为根节点:左子树2个节点,右子树0个节点。可以分成三大类:1 2 3分别为根节点。所以,对于n来说,可以分为n大类。2为根节点:dp[1]3为根节点:dp[2]

2025-08-25 00:16:50 277

原创 爬楼梯变式

【代码】爬楼梯变式。

2025-08-22 23:53:06 306

原创 图论\dp 两题

只不过,爬楼梯的数组是[1,2],即你一次只能爬1或2个台阶。在求dp[i]时,遍历nums数组,假设我们遍历到了j,那么dp[i]加上dp[i-j]即可。即到达第i个阶梯有dp[i]个方法,现在发现还能一次走j个台阶,所以新增方法数等于到达第i-j个台阶的方法数。[a,b]表示方法a调用了方法b。现在要除去所有的可疑方法,就要把方法k调用的(直接与间接)方法都删除。如果存在非可疑方法调用可疑方法,就不删除任何方法。用并查集判断了k和哪些节点是在一个集合中,但没办法处理这个集合中节点的指向关系。

2025-08-20 00:09:27 280

原创 力扣2道dp

dp[i]表示最少需要多少个数的平方来表示整数i,显然这些数落在[1,sqrt(i)]内,我们可以枚举这些数。当枚举到j时,我们还需要取i-j^2,那么需要知道dp[i-j^2],由于子问题与原问题类似,因此使用动态规划。对于dp[i],要么不更新,保持和dp[i-1]一样,要么更新,变为dp[i-2]+nums[i]。两者谁的值更大,决定是否更新。设前i+1间房能搜刮到的最高金额为dp[i]

2025-08-18 23:42:13 356

原创 力扣MySQL(1)

1.欲获取第二高,需要排序。排序使用order by,默认是升序排列,即asc.我们要得到第二高,应该是降序排列,需要使用关键字desc。如果我们只是得到表中第二行的数据,若最高薪水的人有多个,那么我们得到的就是最高薪水了。去重使用distinct。4.临界输出:如果不存在则应返回null,使用ifNull()实现这个功能。注意,不包含第offset_条。只指定一个参数时,表示返回的行数。limit用于限制查询结果返回的行数,常用于分页查询。如果expr为真则返回expr,否则返回null。

2025-07-23 22:50:21 585

原创 对称二叉树、二叉树直径

如上文所说,对于对称位置的L、R,只有当...时才有可能对称,因此我们只需要将L的左节点与R的右节点匹配、L的右节点和R的左节点匹配。考虑使用队列,取出两次对头匹配即可。本质上还是层序遍历,只不过遍历到一个节点的同时也在遍历它对称位置的节点。对于两个对称位置的节点L和R(L在左子树,R在右子树),只有当L的左节点值==R的右节点值且L的右节点值==R的左节点值时,这棵二叉树才有可能对称。另外还需要特判一下nullptr的情况。

2025-07-16 22:27:52 277

原创 翻转二叉树的三种方法

先交换两个子节点,再分别处理子节点,进一步交换。

2025-07-15 22:09:24 214

原创 hot100子串(1)

对于一个起始位置为j,终止位置为i的子串,其元素和为pre[i]-pre[j-1].如果pre[i]-pre[j-1]==k,那么这个子串是符合题意的。移项可得:pre[j-1]=pre[i]-k.我们遍历一次nums可以得到每个位置的前缀和,那么不妨在得到pre[i]的同时,看是否存在前缀和为pre[i]-k的子串,如果存在就将答案增加相应的个数.考虑用unordered_map,因为我们要找“是否存在前缀和为pre[i]-k的子串”,所以key为前缀和,value为这样的子串的个数。

2025-07-14 12:06:11 407

原创 C++:宏

在后面的替换表达式中,省略号位置的参数用宏VA_ARGS替代。#define是个预处理指令,它会在编译前由预处理器进行处理,将代码中的标识符扩展成替换表达式或替换其中的一部分。这条定义中定义了一个print的宏函数,预处理器遇到这样的宏,会将#a替换成以字符串表示的参数a。宏处理的替换表达式可以是任意形式,预处理器在工作时只是做替换、拼接,并不会做语法检查,宏函数add中有两个参数a,b,它会被替换为a+b,a和b会被替换为实际的参数。宏的另外一种定义方式为:函数宏,或宏函数。将两个表达式连接到一起。

2025-07-13 21:58:33 477

原创 hot100滑动窗口

如果两个串是异位词,那么它们的字符出现的次数相同。因此,我们需要判断两个串出现次数不相同的字符的个数是否为0.如果是则二者互为异位词,否则反之。先判断第一个窗口:只需要一个cnt数组,做差即可求出字符出现次数的差值。由于子串中不能有重复字符,因此我们需要统计当前子串每个字符出现的次数。一旦发现右端字符出现了两次,就缩小窗口直至右端字符在窗口内只出现一次。移出后差值变为-1.出现次数不相同的字符个数要加一。左侧移出,右侧移入后,如果出现次数不相同的字符个数为0,那么就是异位词。出现次数不相同的字符个数加一。

2025-07-13 11:10:58 355

原创 hot100链表(1)

方法:假设公共部分长度为z,A的长度为a+z,B的长度为b+z.当pa移动到了尾部,就让它为headB;举个例子,A先跑200m,再跑600m,再跑400m。B先跑400m,再跑600m,再跑200m。法一:最直接的方法,用一个数组存储链表节点的值,用双指针判断是否回文。设原链表为:1 -> 3 -> 5 -> 3 -> 1。处理后:1 -> 3 -> 5 <- 3 <- 1。法二:找中点,反转后半部分。设原链表为:1-> 2 -> 2 -> 1。处理后:1 -> 2 -> 2 <- 1。

2025-07-12 23:44:42 354

.arch7章标准件习题-Model.pdf

.arch7章标准件习题-Model.pdf

2024-11-21

ad2d87c9c1743df621c5b05971f1de49.zip

ad2d87c9c1743df621c5b05971f1de49.zip

2024-10-24

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除