- 博客(46)
- 收藏
- 关注
原创 11 滑动窗口最大值
1、创建一个大小为k的大顶堆,用pair<int,int>构建元素,第一个是数组的值,第二个是数组的下标。创建两个指针,left=0、right=k-1,把指针中间的数字先加入大顶堆,创建临时的vector用于存放最大值。2、从堆顶拿一个元素,判断这个元素的下标是否是在left和right之间的,是则将元素放入答案中,否则将这个堆顶元素删除,继续获取堆顶元素,循环判断。的滑动窗口从数组的最左侧移动到数组的最右侧。3、循环结束条件right要大于数组的下标时,结束循环。不支持随机访问,所以不行)。
2026-07-25 16:05:17
167
原创 10 和为k的子数组
给你一个整数数组nums和一个整数k,请你统计并返回该数组中和为k的子数组的个数。子数组是数组中元素的连续非空序列。22滑动窗口1、检查参数的合法性2、循环数组nums,从0到nums.size()-1,记下标为i,定义满足次数的变量_count=0。3、循环下标i到0的累加和,nums[i]+nums[i-1]、nums[i]+nums[i-1]+nums[i-2]....... nums[i+nums[i-1]+nums[i-2]+nums[0]。判断累加和是否有满足和等于k的。
2026-07-25 14:00:09
231
原创 kv存储主从复制的设计与实现
为了维持一致,命令传播机制会像一个单向的管道,将主节点上执行的、会改变数据的命令,持续不断地发送给所有已连接的从节点。此时,主节点会主动从积压缓冲区中找到这些缺失的命令,并重新发送给从节点,从而保证了数据的最终一致性。为了应对从节点可能发生的短暂断线,Redis 在命令传播的同时,会将所有写命令也写入一个由主节点维护的 复制积压缓冲区(Replication Backlog) 中。的,这意味着主节点在执行完写命令后立即返回客户端结果,无需等待从节点确认,这保证了主节点的高性能。
2026-07-25 13:47:05
326
原创 9 找到字符串中所有字母异位词
给定两个字符串s和p,找到s中所有p的的子串,返回这些子串的起始索引。不考虑答案输出的顺序。[0,6]起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。[0,1,2]起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词。p。
2026-07-22 23:26:54
204
原创 8 无重复字符的最长子串
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。6、在hash表中从左指针到pos的位置的元素删除(或者使用墓碑标记),修改该key值的value=pos,左指针指向pos的位置,右指针继续向前right++,直到右指针指向数组的末尾。4、开始循环右指针往前走,每遇到一个元素查询一下hash中是否有重复的元素,假如没有就往hash中插入一个元素,key为数组的值,value为元素的下标。记录此时hash的长度和len_max比较谁更大,用len_max记录下来。
2026-07-22 23:03:05
223
原创 7 接雨水
2、每一格中能装多少水取决于他左边最高的格子和右边最高的格子,假设为left和right。上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。3、循环找到数组中每一格的len,先创建一个存放左边最高格子的数组,再创建一个右边最高格子的数组。4、计算每一格的储水量,value=len-本身格子的高度,然后所有容量相加。的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。1、判断参数的合法性。
2026-07-20 13:30:10
131
原创 6 三数之和
同样,相同的元素,每一层只能循环一次,判断j不等于i+1时,nums[j]等于nums[j-1]就跳过这一次循环continue。,从0循环到数组末尾。相同的元素,每一层只能循环一次,即判断i不等于0时,nums[i]等于nums[i-1]就跳过这一次循环continue。4、初始化第三层的移动指针k,k指向数组的末尾nums.size()-1;不同的三元组是 [-1,0,1] 和 [-1,-1,2]。输入:nums = [-1,0,1,2,-1,-4]输出:[[-1,-1,2],[-1,0,1]]
2026-07-19 17:42:14
166
原创 5 盛最多水的容器
有 `n` 条垂线,第 `i` 条线的两个端点是 `(i, 0)` 和 `(i, height[i])`。2、创建两个下标指针,left=0,right=size-1,容器长度len=size-1,容器容量value,最大容量value_max。图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。3、循环,计算容量value=len*min(left,right),然后查看left和right谁更小就往中间移动一格。找出其中的两条线,使得它们与 `x` 轴共同构成的容器可以容纳最多的水。
2026-07-19 17:09:59
135
原创 4 移动0
给定一个数组nums,编写一个函数将所有0移动到数组的末尾,同时保持非零元素的相对顺序。,必须在不复制数组的情况下原地对数组进行操作。输入: nums = [0,1,0,3,12] 输出: [1,3,12,0,0]输入: nums = [0] 输出: [0]
2026-07-19 16:54:06
186
原创 CPU缓存的基本原理
在 x86_64 下,一个 Cache Line 是 64 字节,而两个 long long 共 16 字节,它们会被放在同一个 Cache Line 中。CPU 缓存就是基于这两个原理设计的: 每次取数据时,不只是取你需要的那个字节,而是把附近的一整块(Cache Line,通常 64 字节)一起加载进缓存。一般CPU有3级缓存,L1、L2、L3层,L2比L1大,访问速度更慢,L3比L2大,访问速度更慢。CPU 缓存是程序员的“隐形指挥棒”——它不会出现在代码里,但 90% 的性能差距都源于它。
2026-07-19 16:45:03
314
原创 主从同步积压缓冲区的设计与实现
deque 两端插入和删除都是 O(1),内存效率高(比 vector 更适合频繁的头部删除),迭代器不会因为插入和删除操作而失效(比 vector 更稳定),是最适合实现 FIFO 缓冲区的数据结构。问题场景:从节点因网络故障断开连接 30 秒,这 30 秒内主节点执行了 1000 个写命令,从节点重连后,需要同步这 1000 个命令。解决方案:主节点维护一个固定大小的积压缓冲区,缓冲区存储最近执行的写命令,从节点只需获取缓冲区内的增量数据。请求时,主节点首先检查请求的偏移量是否在积压缓冲区中。
2026-07-19 12:18:31
386
原创 3 最长连续序列
给定一个未排序的整数数组nums,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。请你设计并实现时间复杂度为O(n)的算法解决此问题。输入:nums = [100,4,200,1,3,2]输出:4解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。输入:nums = [0,3,7,2,5,8,4,6,0,1]输出:9输入:nums = [1,0,1,2]输出:3。
2026-07-18 17:25:28
183
原创 RDB全量快照备份
RDB (Redis Database) 是 Redis 的核心持久化机制之一,它的核心思想是在指定的时间间隔,为内存中的数据生成一份时间点快照(Point-in-time Snapshot),并保存到一个紧凑的二进制文件中(默认为 dump.rdb)。,但也伴随着的不足。
2026-07-18 15:55:00
286
原创 凡人修仙传
九层之台起累土,万里鹏程始踉跄。君不见:晨星未落炊烟起,夜漏将残纺车忙。百代光阴熔铁骨,千秋功业铸脊梁。结绳记事启鸿蒙,观象制器破天荒。更见那:墨斗牵出鲁班尺,蔡侯纸承千秋史。荣辱且付东流水,悲欢皆入曲中藏。春种秋收循天道,寒来暑往即文章。莫道凡躯终归土,请看:青铜鼎铭英雄血,汗青册载布衣光。最是人间烟火气:陌上赠杏酬知己,雪夜围炉话麻桑。或慕列子御风,或羡彭祖遐龄。仙家云台垂玉露,神君丹鼎炼紫星。然吾观芥子藏须弥,微尘见大千。朝菌不知晦朔,蝼蛄未晓春秋,然各适其适,自得逍遥。
2026-07-18 14:02:45
190
原创 2 字母异位词分组
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。在 strs 中没有字符串可以通过重新排列来形成"bat"。字符串"nat"和"tan"是字母异位词,因为它们可以重新排列以形成彼此。字符串"ate""eat"和"tea"是字母异位词,因为它们可以重新排列以形成彼此。
2026-07-18 12:10:40
175
原创 1 两数之和
给定一个整数数组nums和一个整数目标值target,请你在该数组中找出target的那整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。
2026-07-18 10:55:09
158
原创 C++程序从执行到关闭经历了什么?
start用户交互:你在 Shell 中输入./app。进程复制:Shell 调用fork(),利用 COW 机制快速创建子进程。镜像替换:子进程调用execve(),陷入内核。内核加载:内核解析 ELF,建立 VMA,规划虚拟地址空间,加载动态链接器。动态链接:链接器加载依赖库,完成符号重定位。启动准备:内核设置栈,准备启动参数。缺页加载:CPU 执行第一条指令触发 Page Fault,内核按需从磁盘加载代码和数据。运行时初始化:从_start到,执行全局构造函数。业务逻辑:调用main。
2026-07-12 13:34:43
363
原创 从源码到可执行文件:C++程序的编译过程
编译 main.c│├── 链接 .o 文件│ └── 结果:a.out 包含完整代码,地址固定(静态链接)│├── 链接 .a 静态库│ └── 结果:a.out 提取 .a 中需要的 .o,物理复制进去(静态链接)│└── 链接 .so 动态库└── 结果:a.out 只包含 "引用标记" + "GOT/PLT 表"└── 运行时由 ld-linux.so 将 .so 映射内存,并填充 GOT 表(动态链接)
2026-07-11 18:22:59
339
原创 C++编程常见错误
C/C++应用程序的稳定性,从根本上取决于开发者对内存和资源的精细管理能力。从指针的初始化、边界检查、释放后置空,到资源的及时释放、多线程的同步保护,再到数据溢出的预防,每一个环节都需要严谨的态度和丰富的经验。崩溃原因核心预防手段指针未初始化定义时初始化为nullptr指针越界使用vector/array并启用边界检查野指针释放后置nullptr内存泄漏使用智能指针(RAII)容器堆积定期清理,调用shrink_to_fit句柄泄漏RAII封装(如std::fstream)
2026-07-10 11:30:34
321
原创 ptmalloc内存分配原理
层次模块核心操作备注用户态malloc从tcachefastbinsbins复用内存快速路径,通常无锁用户态 → 内核系统调用 (syscallbrk(小内存) 或mmap(大内存)上下文切换,有一定开销内核态 (虚拟内存)VMA 管理修改堆边界 (brk) 或创建新 VMA (mmap仅在虚拟地址空间预留位置内核态 (物理内存)缺页中断 & 伙伴系统分配物理页框并建立页表映射按需分配,此时才真正消耗物理内存这个设计的精妙之处在于:它通过延迟分配(直到第一次访问才分配物理内存)和用户态缓存。
2026-07-01 23:53:14
388
原创 jemelloc通用内存分配器
每个员工都有自己的专属工具箱,不用大家抢一个公用工具箱,干活更快。size-class 分级分配= 工具箱里有各种尺寸的格子(螺丝刀槽、扳手槽),每种工具都能严丝合缝地放进去,不会晃来晃去浪费空间。让 Redis 这个"超级仓库管理员"在同时应对成千上万个客户请求(多线程)和处理大量小物件(小对象)时,既能干得快(减少锁竞争),又能装得多(减少内存碎片)。
2026-06-30 13:59:53
309
原创 C/C++ 堆与栈的区别——面试完整知识体系
栈空间太小(8MB),大数组或长生命周期对象放栈上会导致溢出。,多线程分配需要加锁(或使用TLS缓存分配器,如 tcmalloc、jemalloc)减小),堆向高地址增长。:栈被销毁,堆内存如果不释放会被OS回收(但良好的程序应该主动释放),旧数据依然残留在内存里,直到被后续栈帧覆盖。:在栈上创建栈帧,参数、返回地址、局部变量入栈。(4/8字节),但它指向的100个int在。:从堆上申请内存,返回指针,程序员负责释放。(Data Segment),不在栈上。(默认8MB),所以线程数过多会耗尽内存。
2026-06-29 18:26:10
318
原创 spdlog高性能异步日志框架编译及使用
由于最近在做一个高性能的kv存储引擎,需要用到一个日志记录模块。本来想手写一个日志模块,但是想想现有的日志框架已经非常成熟了,不如直接借用生产级的框架就好。在我看来,日志模块有几个常用的功能点:高性能吞吐量、异步非阻塞、日志格式、日志轮转等,而spdlog框架恰好都具备。,而且在 C++ 领域里几乎是。在业务线程可以把格式化日志直接丢进无锁队列(MPMC)线程池中直接返回,日志异步写入文件中,对主线程的影响几乎很小。据官方统计,
2026-06-14 20:42:28
174
原创 rm -rf 后恢复文件
所有文件夹都存在 /root/share 中,当我想删除一个文件时,不小心在总文件夹(/root/share)中执行了 rm -rf *。因为 /root/share 是放在 / 目录下面的, / 目录是挂载在 magua-vg的的卷组下,卷名叫 root。执行后我们看到被删除的文件都有还原记录了,在当前文件夹下多了一个 RECOVERED_FILES 的文件夹,这个文件夹里面就存放着被删掉的文件。先 执行 lsblk 看下 /root/share文件夹是挂载在哪一个逻辑卷下面的。
2026-06-14 14:11:00
216
原创 TCP网络收发缓冲区的设计与实现
在网络编程中,数据通常以流的形式到达,而不是以完整的消息为单位。这意味着当你调用read()系统调用时,可能只读取到了消息的一部分,也可能一次性读取到了多个消息的组合。这种不确定性要求我们在应用程序层面维护一个缓冲区来暂存这些数据,直到它们被完整地处理。传统的实现方式是在每次消费数据后将所有剩余数据向前移动,以释放尾部空间。这种做法虽然直观,但效率低下——对于一个包含 1MB 数据的缓冲区,每次消费 1 字节后都要移动 999,999 字节,这显然是不可接受的。
2026-06-07 20:39:06
394
原创 哈希表设计与实现详解
哈希表(Hash Table)是一种通过键(Key)直接访问值(Value)的数据结构。它利用哈希函数将键转换为数组索引,实现 O(1) 平均时间复杂度的查找、插入和删除。删除操作简单直接,O(1) 完成需要标记删除或惰性删除表永远不会"满",链表可无限延伸HashTable 是一个简洁但功能完整特性实现方式冲突解决分离链法(每个槽一条链表)哈希函数FNV-1a 64位扩容机制双表增量 rehash(负载因子 > 2.0)索引计算(2 的幂次容量)关键优化。
2026-06-06 17:27:07
315
原创 Muduo 网络库架构分析
类/模块功能禁用拷贝的基类copyable可拷贝类型标识Atomic原子操作封装Mutex互斥锁Condition条件变量Thread线程封装ThreadPool线程池阻塞队列Timestamp微秒级时间戳Logging日志系统LogFile日志文件管理异步日志Singleton单例模式。
2026-06-01 13:34:56
236
原创 TCP、UDP协议
只要和计算机沾点边的同学,基本上都绕不开这两个大名鼎鼎的网络协议:TCP and UDP 协议。我们来简单描述一下他们的区别,一个网络包走TCP协议传输和UDP协议传输有什么区别?:“儿啊!外套穿了吗?(三次握手)口罩戴了吗?(数据校验)到地方给妈发微信啊!(确认机制)……什么?消息没发出去?重说一遍!(重传机制)”:(把数据包往门外一推)“走你!爱到不到,关我屁事!
2026-04-13 00:07:07
351
原创 Linux IO多路复用
即当buffer长度有变化时,就会触发。【1】每次调用select,都需要把被监控的fds集合从用户态空间拷贝到内核态空间,高并发场景下这样的拷贝会使得消耗的资源是很大的(缺点) 【2】能监听端口的数量有限,单个进程所能打开的最大连接数由。关注点是数据是否有无,只要读缓冲区不为空,写缓冲区不满,那么epoll_wait就会一直返回就绪,水平触发是epoll的默认工作方式。FD_ISSET 判断服务器的fd是否还存在集合中就绪,如果存在,则有新的连接进来,使用accept接受新的连接,记录客户端的fd。
2026-04-07 14:29:22
406
原创 C语言内存池
内存池(Memory Pool)是一种预先从系统堆中申请一大块内存,然后由程序自己管理这块内存分配和释放的技术。相比直接调用 new/delete 或 malloc/free,效率更高,并且更加容易管理内存,避免内存泄漏。
2026-04-05 02:51:20
224
原创 C语言线程池
就好比刚刚的厨师,我们让他做完一个任务后,就解聘它了,有新任务时又重新招聘一个厨师,这样频繁的解聘和招聘厨师成本很大。当有任务需要处理时,从池子里取出空闲的线程执行任务,任务执行完不销毁线程,而是返回池中等待下一个任务。我们以做三道菜品的任务来描述一下,单线程和多线程工作过程的区别,最后再总结它的优点和使用场景。程序开始=》做菜品1=》上菜品1=》做菜品2=》上菜品2=》做菜品3=》上菜品3=》任务完成。【2】线程池可以固定线程的数量,避免创建大量的线程,导致系统资源耗尽。
2026-03-29 13:53:31
364
原创 3 最长连续序列
但仔细分析这个过程,我们会发现其中执行了很多不必要的枚举,如果已知有一个 x,x+1,x+2,⋯ ,x+y 的连续序列,而我们却重新从 x+1,x+2 或者是 x+y 处开始尝试匹配,那么得到的结果肯定不会优于枚举 x 为起点的答案,因此我们在外层循环的时候碰到这种情况跳过即可。我们考虑枚举数组中的每个数 x ,考虑以其为起点,不断尝试匹配 x+1 , x+2 ,.....是否存在假设最长匹配到了 x+y,那么以 x 为起点的最长连续序列其长度则为 y+1。若是遇到相邻的两个数,直接跳过。
2024-06-18 18:14:32
331
原创 金钱和理智
但我告诉你,你想要的不是这些。然后,你也将努力挣到一大笔钱,并把目标定的更高,继续追逐你的发财梦。但是,你要明白,并非所有的成功都是靠努力换来的,并非所有的贫穷都是因为懒惰造成的。绝大多数债务犹如毒品:这是一阵转瞬即逝、代价昂贵的快感,只会拖累你多年,让你的生活处处受限。你的收入中有多少比例要存起来与你赚多少没有什么关系,主要还是和你的开支有关。债务是你对未来的索取,你总是为了当面的获得而放弃未来,你很快就会对此习以为常。但是,你要知道,你适应新环境的能力比你想象的要更加强大,你的目标不仅仅是追求财富。
2024-04-06 22:00:15
509
1
原创 快速排序(C语言)
对于包含n个数的输入数组来说,快速排序是一种最坏情况时间复杂度为Θ() 的排序算法。虽然最坏情况时间复杂度很差,但是快速排序通常是实际排序应用中最好的选择,因为它的平均性能非常好,另外它还能够进行原址排序,甚至在虚存环境中也能很好的工作。
2023-08-02 21:14:18
162
原创 堆排序算法
在交换之后,下标largest的结点是原来的Arr[largest]的值,于是以该结点为根的子树又有可能会违反最大堆的性质。在剩余的结点中,只有一个元素不满足最大堆的性质,那就是我们刚刚换上去的Arr[1],这时候我们只需要调用一次max_heapify(Arr,1)维护堆,剩下的结点又编程了一个n-1的大顶堆了。:结点i的所有子结点都满足最大堆的性质,只有i结点不满足最大堆的性质,因为Arr[i]可能小于其孩子节点,这样就违背了最大堆的性质。这两种堆中,结点的值都要满足堆的性质。
2023-07-31 15:58:36
249
1
原创 C语言定时关机恶搞
首先叙述一下这个程序的功能:1 :开机自启动,关机以后再开机,程序自动在后台运行,到时间自动关机。2:窗口是隐藏的,启动的时候没有任何现象,但是在任务管理器能看到3:全年,非周末时间,早上6点到9点,中午12-2点,晚上10点之后都会自动关机该程序适合在校大学生舍友打游戏或者看直播时大喊大叫时使用,效果非常明显,且持续效果久,且不易发现。控制台窗口隐藏程序:#pragma comment( linker, "/subsystem:\"windows\" /entry:\"m
2023-07-31 11:33:32
288
1
原创 单例设计模式C++
什么是单例设计模式?单例模式是一种对象创建型模式,使用单例模式,可以保证一个类只生成一个唯一对象。也就是说,整个程序只能创建一个用单例设计模式设计的类。单例模式实现步骤懒汉式:在类中创建对象,并返回静态指针给类外的对象使用 1:构造函数私有化 2:提供静态指针 3:提供静态方法,返回静态指针饿汉式:在类外创建对象,赋给类中静态指针,作为全局变量使用为什么要使用单例模式?1、需要生成唯一序列的环境。2、需要频繁实例化,然后销毁对象。...
2022-05-30 20:17:25
170
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅