- 博客(32)
- 收藏
- 关注
原创 动态规划-最长上升子序列问题
本文介绍了最长上升子序列(LIS)的动态规划解法及其应用。首先定义LIS问题,即找到无序整数数组中最长的严格递增子序列长度。通过O(n²)的动态规划算法,使用dp[i]表示以nums[i]结尾的最长子序列长度,遍历比较前序元素进行状态转移。随后以合唱队形问题为例,将其转换为LIS问题求解:计算每个位置作为峰顶时,左侧的递增序列长度f[i]和右侧递减序列长度g[i](等价于反向递增),最终最少出列人数为n-max(f[i]+g[i]-1)。文中提供了完整代码实现和详细思路分析,展示了LIS问题的典型应用场景。
2026-07-16 15:18:25
363
原创 拓扑排序-算法详解
本文介绍了拓扑排序的基本概念及两种主流实现算法(Kahn算法和DFS算法)。拓扑排序是对有向无环图顶点进行线性排序的算法,要求每条有向边(u,v)中u始终出现在v之前。文章重点讲解了基于BFS的Kahn算法实现步骤,包括入度计算、队列处理和结果验证,并通过两个代码示例(C++实现)演示了如何解决课程安排问题。最后指出若排序顶点数不足总顶点数则说明存在环,无法完成拓扑排序。
2026-07-16 14:17:38
352
原创 一篇文章带你学透动态规划背包问题
力扣上的背包问题,很少会直接以“纯01背包”或“纯完全背包”的裸题形式出现,更多时候,它们被包装在各种应用题里,需要你自己识别并转化为背包模型。因此,死记硬背公式解法并不可取,真正重要的是理解背包问题背后的核心原理,掌握其思维范式——这样,当遇到变形题目时,你才能灵活地将它还原为熟悉的背包结构。在我看来,背包问题乃至所有动态规划问题,最大的难点都在于如何找到合适的状态表示。这种能力不是靠记住几个模板就能获得的,它需要大量针对性的刷题训练,在反复试错中逐渐培养出“题感”。算法学习远不止于刷题本身。
2026-07-15 10:06:42
437
1
原创 震惊!!!学了这么久的DFS/BFS你都用错了!
算法选择:理解 BFS 和 DFS 的本质差异,根据问题特性选择合适算法,不要惯性用 DFS 解决所有搜索问题。回溯机制:DFS 的回溯是穷举路径的基础,而 BFS 的“一层层扩展”则天然保证最短路。算法学习不只是刷题,更要在错误和思考中总结。希望这篇文章能帮你少踩一些坑,更清晰地理解这两种基础搜索算法。如有疑问,请在评论区留言,我会尽力解答。博客首发于CSDN,转载请注明出处。
2026-07-11 11:53:58
441
原创 TCP/IP协议族详解:数据在互联网中是如何“漂流”的?
当你在浏览器输入网址,按下回车,网页瞬间加载,当你在与朋友聊天时,按下消息发送键,消息就会精准无误的显现在对方手机中,网络究竟是什么,数据在互联网中是如何“漂流”的?本文将为你答疑解惑。
2026-03-14 22:48:52
230
原创 TCP/IP协议族详解:应用层协议HTTP
HTTP协议是⼀个⽆连接、⽆状态的协议,即每次请求都需要建⽴新的连接,且服务器不会保存客⼾端的状态信息。这个Location选项是⼀个标准的HTTP响应头部,⽤于告诉浏览器应该将请求重定向到哪个新的URL地址。当然,通过这种方式传递参数是非常危险的,因为是明文传递,所以一般不会用这种方式传递用户名密码等敏感内容,URL的长度也是有限制的,所以不能传递长数据。HTTP中的Connection字段是HTTP报文头的一部分,它主要用于控制和管理客户端与服务器之间的连接状态。⽤途:⽤于请求URL指定的资源。
2026-03-14 22:44:05
1006
4
原创 DP 从放弃到拿捏:一份持续更新的动态规划题解清单(二)
直观解法是模拟游戏过程,但直接模拟(如使用循环链表)的时间复杂度为 O(n*m),无法满足 O(n) 的要求。使用队列或循环链表模拟报数过程,但每次删除需要 O(m) 的时间,总体 O(n*m),对于 n=5000, m=10000 可能超时,且空间复杂度 O(n)。,而外圈的m-1出列后就等价于内圈,所以外圈最终留下来的人的编号就是m+k,考虑到m>n的情况 ,最终留下来的人是。图中内圈表示 n-1 个人(编号 0 ~ n-2)围成一圈,数到 m-1 的人出列。:O(n),仅需一次循环。
2026-02-25 20:33:39
450
原创 DP 从放弃到拿捏:一份持续更新的动态规划题解清单(一)
组合,数量级约为 10^15,会超过 32 位 int 范围,因此必须使用 64 位整数(如 C++ 的。实际上如果字符串由这三个字母组成,且顺序允许,最大子序列数可能达到组合数级别,比如。h[i] 表示:字符串 str 中 [0, i] 区间内,有多少个 "sh"y[i] 表示:字符串 str 中 [0,i] 区间内,有多少个 "shy":我们依次读取字符,每读到一个字符,就考虑它能如何延续已有的部分子序列。s[i] 表示:字符串 str 中 [0, i] 区间内,有多少个"s"
2026-02-25 13:37:40
918
2
原创 C++ STL unordered_set 与 unordered_map 完全指南
在C++标准模板库(STL)中,和是基于哈希表实现的容器,提供了平均O(1)时间复杂度的查找、插入和删除操作。与有序容器(setmap)不同,它们不维护元素的任何特定顺序。// 元素个数: 5// 是否为空: 0(false)// 可存储的最大数量// operator[] - 访问或插入元素// 修改现有元素// 插入新元素// 访问元素// at - 访问元素,越界时抛出异常try {
2026-01-18 16:22:29
822
1
原创 Linux常用指令详解
在Linux世界中,命令行界面是程序员和系统管理员最强大的工具之一。本文将为初学者和有经验的用户介绍Linux中最常用、最实用的指令,每个指令都配有实际使用样例,帮助你快速掌握这些核心工具。:显示当前目录下的文件和子目录。:删除文件或目录(谨慎使用!:打印当前工作目录的完整路径。:创建新文件或更新文件时间戳。:实时显示系统状态和进程信息。:估算文件/目录的磁盘使用量。:查看文件开头或结尾部分。:在文件中搜索指定模式。:更改文件或目录的权限。:更改文件的所有者和组。:显示当前运行的进程。
2026-01-18 14:32:49
620
原创 C++ STL string 用法详解与示例
本文全面介绍了C++标准模板库(STL)中string类的使用方法。内容包括字符串的创建初始化、基本操作(获取信息、访问修改字符)、修改操作(追加、插入、删除、替换)、查找与子字符串提取、字符串比较、数值与字符串相互转换、输入输出操作等核心功能。通过大量示例代码演示了各方法的实际应用,并详细说明了size()/length()、at()/[]等方法的区别及使用场景。文章还介绍了字符串内存管理(resize/reserve)和交换操作等高级功能,为C++开发者提供了完整的字符串处理参考指南。
2025-12-17 16:36:24
901
原创 C++11右值引用:从移动语义到完美转发
• Function(T&& t)函数模板程序中,假设实参是int右值,模板参数T的推导int,实参是int左值,模板参数T的推导int&,再结合引⽤折叠规则,就实现了实参是左值,实例化出左值引⽤版本形参的Function,实参是右值,实例化出右值引⽤版本形参的Function。• 变量表达式都是左值属性,也就意味着⼀个右值被右值引⽤绑定后,右值引⽤变量表达式的属性是左值,也就是说Function函数中t的属性是左值,那么我们把t传递给下⼀层函数Fun,那么匹配的都是左值引⽤版本的Fun函数。
2025-11-29 15:30:36
1156
原创 深入浅出C++多态:从虚函数到动态绑定的完全指南
多态是⼀个继承关系的下的类对象,去调⽤同⼀函数,产⽣了不同的⾏为。⽐如Student继承了Person。Person对象买票全价,Student对象优惠买票。实现多态还有两个必须重要条件:• 必须是基类的指针或者引⽤调⽤虚函数• 被调⽤的函数必须是虚函数,并且完成了虚函数重写/覆盖。
2025-11-21 13:35:13
1012
原创 C++继承:解锁面向对象编程的基石
继承(inheritance)机制是⾯向对象程序设计使代码可以复⽤的最重要的⼿段,它允许我们在保持原有类特性的基础上进⾏扩展,增加⽅法(成员函数)和属性(成员变量),这样产⽣新的类,称派⽣类。继承呈现了⾯向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的函数层次的复⽤,继承是类设计层次的复⽤。比如我们要设计两个类Student和Teacher,Student和Teacher都有姓名/地址/电话/年龄等成员变量,都有identity⾝份认证的成员函数,设计到两个类⾥⾯就是冗余的。
2025-11-20 16:25:33
816
原创 leetcode17.电话号码的数字组合(题目详解)
不难发现,digits有几个数字,就有几层循环层数,但是我们的代码的循环层数又不能改变,怎么办呢?这里就可以用递归来解决,递归的深度就是digits的数字个数,递归内部再用循环来遍历每个数字对应映射的所有字母。先考虑只输入一个数字的情况,例如digits=“2”,只需遍历一遍“abc“即可。若digits=“23”,就要经历两次遍历。如下图所示:digits="234"
2025-11-05 20:59:41
325
原创 解锁C++核心魔法:一文读懂“类”与“对象”的奇妙世界(第三期)
• 内部类本质也是⼀种封装,当A类跟B类紧密关联,A类实现出来主要就是给B类使⽤,那么可以考虑把A类设计为B的内部类,如果放到private/protected位置,那么A类就是B类的专属内部类,其他地⽅都⽤不了。• 友元提供了⼀种突破类访问限定符封装的⽅式,友元分为:友元函数和友元类,在函数声明或者类声明的前⾯加friend,并且把友元声明放到⼀个类的⾥⾯。• 如果⼀个类定义在另⼀个类的内部,这个内部类就叫做内部类。• 友元类的关系是单向的,不具有交换性,⽐如A类是B类的友元,但是B类不是A类的友元。
2025-10-28 13:45:14
844
原创 解锁C++核心魔法:一文读懂“类”与“对象”的奇妙世界(第二期)
但是这三个函数有且只有⼀个存在,不能同时存在。• 之前我们实现构造函数时,初始化成员变量主要使⽤函数体内赋值,构造函数初始化还有⼀种⽅式,就是初始化列表,初始化列表的使⽤⽅式是以⼀个冒号开始,接着是⼀个以逗号分隔的数据成员列表,每个"成员变量"后⾯跟⼀个放在括号中的初始值或表达式。3. 没有显式实现时,编译器会⾃动⽣成⼀个默认赋值运算符重载,默认赋值运算符重载⾏为跟默认拷⻉构造函数类似,对内置类型成员变量会完成值拷⻉/浅拷⻉(⼀个字节⼀个字节的拷⻉),对⾃定义类型成员变量会调⽤他的赋值重载函数。
2025-10-27 15:49:31
1139
原创 解锁C++核心魔法:一文读懂“类”与“对象”的奇妙世界(第一期)
public: //访问限定符//放置共有的属性与⽅法protected://放置保护的属性与⽅法private://放置私有的属性与⽅法● class为定义类的关键字,Date为类的名字,{}中为类的主体,注意类定义结束时后⾯分号不能省略。类体中内容称为类的成员:类中的变量称为类的属性或成员变量;类中的函数称为类的⽅法或● public修饰的成员在类外可以直接被访问;
2025-10-27 14:14:08
912
原创 排序算法全景指南:从冒泡到快排,一次搞定(第二期)
将已有序的⼦序列合并,得到完全有序的序列;排序阶段:将大文件分割成若干个能装入内存的小片段,每次读入一个片段到内存,用高效的内排序算法(如快速排序)对其进行排序,然后将这个有序的小片段(称为“归并段”或“顺串”) 写回磁盘。关注点:主要关注时间和空间的复杂度,即如何减少数据之间的比较次数和移动次数。定义:当待排序的记录数量非常庞大,无法一次性全部加载到内存中,必须借助外部存储器(如硬盘) 进行分批处理,然后再合并的排序过程。
2025-10-15 12:17:54
1191
4
原创 排序算法全景指南:从冒泡到快排,一次搞定(第一期)
⾸先从右向左找出⽐基准⼩的数据,找到后⽴即放⼊左边坑中,当前位置变为新的"坑",然后从左向右找出⽐基准⼤的数据,找到后⽴即放⼊右边坑中,当前位置变为新的"坑",结束循环后将最开始存储的分界值放⼊当前的"坑"中,返回当前"坑"下标(即分界值下标)借助栈,利用后进先出的特性,基准值有序后,先将右区间下标入栈,再将左区间下标入栈,下次循环先出栈两次,取得区间范围,进行排序,再重复以上过程(类似于二叉树层次遍历的过程)算法思路:创建前后指针,从左往右找⽐基准值⼩的进⾏交换,使得⼩的都排在基准值的左边。
2025-10-15 09:30:00
922
4
原创 leetcode 138. 随机链表的复制(题目详解)
这道题复制next指针很容易,只需要遍历原链表,将原链表每个节点的val赋给我们malloc出的新节点就行了。真正的难点在于怎么拷贝random指针,显然,如果我们一开始就单独创建一个新链表,那么random指针就永远无法处理,因为原链表与新链表每个节点的地址都不同,就算我们记录下random指针指向的节点存的val,然后再遍历新链表找相同的值,也是不行的,因为一个链表中可能有多个节点存了相同的val。第三次遍历一遍原链表,只需将我们新建的节点分离出来,连成一条新链表就行了。那么这题该怎么解呢?
2025-10-10 13:59:20
489
原创 从零开始实现贪吃蛇小游戏(C语言版第二期)
可以看到,ASCII字符集共包含128个字符,在英语 国家中,128个字符是基本够⽤的,但是,在其他国家语⾔中,⽐如,在法语中,字⺟上⽅有注⾳符 号,它就⽆法⽤ASCII码表⽰。于是,⼀些欧洲国家就决定,利⽤字节中闲置的最⾼位编⼊新的符 号。在游戏运⾏的过程中,蛇每次吃⼀个⻝物,蛇的⾝体就会变⻓⼀节,如果我们使⽤链表存储蛇的信息,那么蛇的每⼀节其实就是链表的每个节点。setlocale 的第⼀个参数可以是前⾯说明的类项中的⼀个,那么每次只会影响⼀个类项,如果第⼀个参数是LC_ALL,就会影响所有的类项。
2025-09-30 14:58:37
1326
原创 从零开始实现贪吃蛇小游戏(C语言版第一期)
Windows这个多作业系统除了协调应⽤程序的执⾏、分配内存、管理资源之外,它同时也是⼀个很⼤ 的服务中⼼,调⽤这个服务中⼼的各种服务(每⼀种服务就是⼀个函数),可以帮应⽤程序达到开启 视窗、描绘图形、使⽤周边设备等⽬的,由于这些函数服务的对象是应⽤程序(Application),所以便 称之为ApplicationProgrammingInterface,简称API函数。WIN32API也就是MicrosoftWindows 32位平台的应⽤程序编程接⼝。
2025-09-29 18:09:54
1268
原创 单链表经典例题解析(1)
定义两个指针,一开始都指向头节点,慢指针每次向后移动一位,快指针每次向后移动两位,这样当快指针指向链表末尾时,慢指针刚好指向链表的中间节点。最容易想到的思路当然就是先遍历一遍链表,记下链表的长度,然后再遍历到链表的中间值,最后返回该节点的地址。注意: while(fast&&fast->next)中的判断条件不能反过来写。如下图,当链表节点数为偶数时,fast指针最后会指向空,而空指针解引用会报错。是不是感觉用这种方法写出来的代码更加简洁漂亮了呢,而且运行效率也更高了。
2025-09-25 22:55:40
352
原创 由浅入深带你精通C语言指针!(第三期)
所以,根据数组名是数组⾸元素的地址这个规则,⼆维数组的数组名表⽰的就是第⼀⾏的地址,是⼀ 维数组的地址。根据上⾯的例⼦,第⼀⾏的⼀维数组的类型就是 型就是数组指针类型 int [5] ,所以第⼀⾏的地址的类 int(*)[5]。那就意味着⼆维数组传参本质上也是传递了地址,传递的是第⼀ ⾏这个⼀维数组的地址,那么形参也是可以写成指针形式的。⾸先我们再次理解⼀下⼆维数组,⼆维数组起始可以看做是每个元素是⼀维数组的数组,也就是⼆维数组的每个元素是⼀个⼀维数组。那么⼆维数组的⾸元素就是第⼀⾏,是个⼀维数组。
2025-09-22 15:11:52
1358
2
原创 由浅入深带你精通C语言指针!(第二期)
同理arr[i] 应该等价于*(arr+i),数组元素的访问在编译器处理的时候,也是转换成⾸元素的地址+偏移量求出元素的地址,然后解引⽤来访问的。parr[i]是访问parr数组的元素,parr[i]找到的数组元素指向了整型⼀维数组,parr[i][j]就是整型⼀维数组中的元素。1.sizeof(数组名),sizeof中单独放数组名,这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩, 单位是字节。*ppa 通过对ppa中的地址进⾏解引⽤,这样找到的是这样找到的是pa , *ppa 其实访问的就是 pa。
2025-09-21 13:52:54
1409
2
原创 strstr()函数使用详解
如果第一次出现b就开始比较两个字符串,会错误判定为str2没有出现在str1中,返回NULL,这样代码就出错了,所以我们要引入一个cp指针来存当前比较到的位置,确保每一个字符都做过比较的起点。翻译:函数返回字符串str2在字符串str1中第⼀次出现的位置,没有出现过则返回NULL。2.函数返回字符串str2在字符串str1中第⼀次出现的位置,没有出现过则返回NULL。写一个函数,判断一个字符串是否为另外一个字符串旋转之后的字符串。例如:给定s1 =AABCD和s2 = BCDAA,返回1。
2025-09-20 15:49:25
601
1
原创 由浅入深带你精通C语言指针!(第一期)
相信对不少同学来说,指针就像C语言学习道路上的大BOSS,初次遇到它,一定会被各种引用解引用的操作弄的晕头转向,我在初学的时候,也是费了好大的劲才逐渐掌握指针的各种知识点。如果你现在正被指针的概念和用法所困扰的话,恭喜你,来对地方了,本文将由浅入深带你精通C语言指针!
2025-09-19 16:50:38
1482
1
原创 C语言实现扫雷(详解版)
另外,假设我们排查(2,5)这个坐标时,我们访问周围的⼀圈8个⻩⾊位置,统计周围雷的个数是1 假设我们排查(8,6)这个坐标时,我们访问周围的⼀圈8个⻩⾊位置,统计周围雷的个数时,最下⾯的三 个坐标就会越界,为了防⽌越界,我们在设计的时候,给数组扩⼤⼀圈,雷还是布置在中间的9*9的坐 标上,周围⼀圈不去布置雷就⾏,这样就解决了越界的问题。一个棋盘上,有若干个雷,当我们点击非雷区时,会展开一片没有雷的区域,这片区域的边界会显示其周围8格雷的数量,我们的目标就是找到所有的雷或者展开所有无雷的区域。
2025-09-16 10:00:00
1244
原创 学习笔记——字符指针变量
原来,这⾥str3,str4,str5,str6指向的是同⼀个常量字符串(加不加const都不会影响)。C/C++会把常量字符串存储到单独的⼀个内存区域, 当⼏个指针指向同⼀个字符串的时候,他们实际会指向同⼀块内存。但是⽤相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块。所以str1和str2不同,str3,str4,str5,str6相同。课上写的一道字符串相关的笔试题,我觉得很有意思,这里分享给大家。给大家思考一小会儿,觉得答案是什么呢?
2025-09-15 10:00:00
152
原创 VS2022中gets()函数无法使用原因及解决办法
gets()函数的主要问题是它无法检查输入字符串的长度,这极易导致缓冲区溢出。如果用户输入的字符数超过了为存储它而分配的数组大小,多出的字符就会覆盖相邻的内存区域。这可能导致程序崩溃、数据损坏,甚至被恶意利用来执行任意代码。鉴于其严重安全性问题,gets()函数已在 C11 标准中被正式移除。像 Visual Studio 2022 这样的现代编译器通常默认遵循更严格的安全标准,因此默认不再支持 gets()函数。使用gets()函数编译时会报错(如 C4996 或 “未定义标识符”)。
2025-09-13 15:58:14
1008
原创 c语言中的分支与循环——易忽略知识点整理
注:本文不介绍分支与循环的基本概念,而是从一些细小的,易忽略的知识点入手,旨在帮助读者加深对分支与循环的理解。
2025-09-13 14:22:26
330
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅