- 博客(48)
- 收藏
- 关注
原创 hot100专题-栈,堆
利用栈后进先出的特性遇到左括号直接入栈遇到右括号判断,首先看是不是空,栈空了就说明没有与之匹配的左括号然后取栈顶元素进行判断。
2026-02-23 14:37:43
663
原创 hot100二分查找专题
当我们用基础框架找到 nums[mid] == target 时,我们不能再像以前那样直接 return mid 了,因为这个 mid 可能只是连续目标值中间的某一个,并不是我们要找的“开始位置”或“结束位置”。寻找开始位置(左边界): 当我们发现 nums[mid] == target 时,说明当前找到了目标,但它左边可能还有目标。先用一个变量把当前这个 mid 记下来,然后绝不手软地砍掉右半边(让 right = mid - 1),继续在左半区间寻找有没有更早出现的目标值。
2026-02-22 14:30:37
679
原创 hot100回溯专题
思路:回溯算法的经典三要素:1.路径:需要一个一维数组path记录当前路径2.选择列表:选择的就是nums数组里面的数字,只不过不能选择自己了,所以需要一个判断条件,判断自己有没有被选择过3.结束条件:当 path 收集的数字个数等于 nums 的长度时,说明一个完整的全排列诞生了,把它塞进结果集 res 里,然后返回。回溯最重要的就是最有一步撤销操作,当结束条件返回的时候,就可以撤销这一步的操作(撤销约等于回溯)
2026-02-21 10:25:54
375
原创 C++常用关键字考察
如果如果在 header.h 里写 static int count = 0;,然后 A.cpp 和 B.cpp 都 include 了它结果是A.cpp 有了一个私有的 count,B.cpp 也有了一个私有的 count。
2026-02-03 16:09:12
725
原创 算法基础-哈希表
上面给出了 hash 函数的实现,那么你肯定也会想到,如果两个不同的 key 通过哈希函数得到了相同的索引,怎么办呢?2、哈希表里面已经装了太多的 key-value 对了,这种情况下即使哈希函数再完美,也没办法避免哈希冲突。对于第一个问题没什么好说的,开发编程语言标准库的大佬们已经帮你设计好了哈希函数,你只要调用就行了。1、哈希函数设计的不好,导致 key 的哈希值分布不均匀,很多 key 映射到了同一个索引上。对于第二个问题是我们可以控制的,即避免哈希表装太满,这就引出了「负载因子」的概念。
2026-02-02 15:57:09
635
原创 算法-贪心算法
计算:如果我今天卖出(价格是 prices[i]),减去那个历史最低价,能赚多少?维护一个我现在这个节点的边界,在维护一个我现在这个节点边界范围内可以到达下一个节点可以到达的最远距离。i>cover 证明现在遍历过得这些节点都到不了 数组的后面,跳出循环返回false。记录:截至目前为止,我见过的最低价格 (min_price) 是多少?思路通过维护一个cover代表现在遍历过的节点中,能跳到的最远下标。先设立一个数组,记录每一个数字最后出现的位置。超过我此刻这个节点的边界就必须得跳一步。
2026-02-02 10:40:14
448
原创 算法-字典树
如果搜索到index == word.size()的时候,返回字母尾巴的isEnd(注意尾巴的isEnd都是true)看看下一个节点里面的word是不是空的(建树的时候在最后一个节点哪里安排上word,不是最有一个节点都是空)在dfs里面,首先判断新进入的节点是不是根节点,因为根节点是空的,我们需要跳过他,去找真正的第一个节点。首先传入要搜索的词,当前搜索到 word 的第几个字符,当前处在 Trie 树的哪个节点。遍历26个子节点,如果他们是的isEnd是True(代表之前出现过)(体现原题目中的。
2026-02-01 17:10:31
740
原创 算法---二叉堆
当push进一个数值,和队列的尾部相比,如果比队列的尾部大,则证明原来的队列的尾部永远不可能是最大值,将未来的尾部pop掉,再重新比较新的尾部和新来的数值,直到尾部比新进来的数值大,此时将新进来的数值push进队列。当移动窗口的时候,判断左边出队列这个是不是当前的最大值(q.front)如果是则pop出去,如果不是就证明这个数之前已经被淘汰掉了,因为举个例子,342,在4进入的时候,3就已经被剔除掉了。思路就是维护一个小堆,堆顶最小,然后往里面加数字,加的数字要是大,就把原来的小堆顶pop出来。
2026-01-30 10:18:09
751
原创 算法--二叉搜索树
然后左右两边是独立的区间,而且左边区间 [1, i-1] 也是要构造 BST,右边 [i+1, n] 也是要构造 BST。如果有两个叶子结点,那么删除后一般是用右子树里面最小的那个节点(右子树递归左子树(这个值与删除的这个值最接近))由于二叉搜索树的特性,有几种二叉树之和节点个数有关和具体的数值无关,比如123和234的二叉搜索树是一样的。把这个值复制给删除的那个位置,然后像情况1或者情况2(有一个右叶子/右子树)那样删除叶子节点即可。size 的定义:以当前节点为根的子树中节点的总个数。
2026-01-28 10:27:41
921
原创 算法-数组双指针技巧
动窗口可以归为快慢双指针,一快一慢两个指针前后相随,中间的部分就是窗口。思路就是用一个快慢指针,注意if哪里,如果两个一样,快指针就先往后走,知道找到不一样的时候先把slow往前进一位然后在替换掉这个地方的数。加入BAA 进货单就是B:1 A:2(本来是第一次出现从0开始算,但是有一个++,就从1开始算了)首先定义左指针有指针,一个vaild(用于判断购物车里面是否满足要求)思路,首先准备两个map,一个是进货单,一个是购物车。要原地移除元素,和原来模版的区别就是。有快慢指针和左右指针。
2026-01-27 08:46:02
368
原创 二分查找算法
先用个辅助函数计算 我这个时候的速度k 吃完用时多少,方便后文判断。跟上一题类似,用一个辅助函数,确定一个容量下我可以几天弄完。左边界是数组最大的那个容量(小于这个数组永远也送不完)分别对应二分查找数组,二分查找左边界,二分查找右边界。右边界是数组总和(一天送完)最快速度是最大堆的香蕉数。用二分搜索找最快速度。(偏移量,便宜k个)
2026-01-27 08:45:47
161
原创 滑动窗口模版
动窗口可以归为快慢双指针,一快一慢两个指针前后相随,中间的部分就是窗口。滑动窗口算法技巧主要用来解决子数组问题,比如让你寻找符合某个条件的最长/最短子数组。加入BAA 进货单就是B:1 A:2(本来是第一次出现从0开始算,但是有一个++,就从1开始算了)首先定义左指针有指针,一个vaild(用于判断购物车里面是否满足要求)和之前的区别就是第二个while循环哪里,判断什么时候缩减窗口。思路,首先准备两个map,一个是进货单,一个是购物车。通过维护一个单调队列去解决滑动窗口最大值的问题。
2026-01-27 08:45:35
224
原创 算法-链表-递归
在写代码之前,你必须先明确 reverseList(head) 这个函数的功能是什么,输入输出是什么。输入:一个链表的头节点 head。功能:把这个链表反转。输出:反转后的新头节点。契约:只要你给我一个链表,我不管你用什么方法,你必须还给我一个反转好的链表头。
2026-01-27 08:45:15
532
原创 基础数据结构-栈与队列
现在给你出这么一道题:输入一个数组 nums,请你返回一个等长的结果数组,结果数组中对应索引存储着下一个更大元素,如果没有更大的元素,就存 -1。重点就是下面那个while循环,将两个高个中间的数字全都剔除掉,剩下的那个栈顶就是下一个更大的元素。思路就是利用map将对应关系存起来(因为nums1是nums2的子集所以map一定能查到)思路就是把原有数组延长一倍,但是不是真的重新开辟一个空间,而是用取模运算实现循环。就是原来栈是存数值,现在是存下标,while循环剔除的是下标。用标准库容器的list实现。
2026-01-26 15:34:21
397
原创 手写LRU缓存系统
那么,什么样的数据,我们判定为「有用的」的数据呢?首先要接收一个 capacity 参数作为缓存的最大容量,然后实现两个 API,一个是 put(key, val) 方法存入键值对,另一个是 get(key) 方法获取 key 对应的 val,如果 key 不存在则返回 -1。3、每次访问 cache 中的某个 key,需要将这个元素变为最近使用的,也就是说 cache 要支持在任意位置快速插入和删除元素。,以区分最近使用的和久未使用的数据,当容量满了之后要删除最久未使用的那个元素腾位置。
2026-01-26 15:34:04
304
原创 算法-回溯算法
其中比如说第二层的2,[2] 就是「路径」,记录你已经做过的选择;只是新加一个计数器,其余没什么变化,记得totalNQueens函数里面的count不要加int ,加了int就是一个局部变量会掩盖私有成员里的全局变量(要修改的是这个全局变量)结束:没有选择可选,记录结果,回溯(退回到上一层,撤销 3,尝试别的,虽然这里没别的了)。123的全排列123,132,213,231,321,321。选了 1,路径变成 [1],剩下的选择是 {2, 3}。选了 2,路径变成 [1, 2],剩下的选择是 {3}。
2026-01-26 15:33:33
1110
原创 算法-深度优先搜索
处理网格类 DFS,你只需要记住这套“三步走”口诀:边界检查、标记访问、递归扩散。这里的思路就是先从四边进行把不符合条件的岛屿都淹没。剩下的内部的有几个就算几个。
2026-01-26 15:33:09
274
原创 算法-动态规划
我在乎的是**“我是排在第几个的人”以及“我能不能接在别人后面”**。思考:dp[i] 是怎么由之前的状态(比如 dp[i-1], dp[i-k])推导出来的?01背包问题,和前文的零钱问题(无限背包,零钱无限用)和最长递增子序列(序列dp,关注下标)不同。如果顺序排列的话就会导致元素的重复使用(我之前用这个数填过一次了,后来我继续使用这个数字去填)(比如:凑满金额 i 所需的最少硬币数)。回头看:回头看 0 到 i-1 的所有下标(位置回溯)。最开始的情况是什么?dp[i] 的 i 代表数组下标。
2026-01-26 15:32:43
1241
原创 基础数据结构-循环链表
上面只是让大家对环形数组有一个直观地印象,环形数组的关键在于,它维护了两个指针 start 和 end,start 指向第一个有效元素的索引,end 指向最后一个有效元素的下一个位置索引。当 start, end 移动超出数组边界(< 0 或 >= arr.length)时,我们可以通过求模运算 % 让它们转一圈到数组头部或尾部继续工作,这样就实现了环形数组的效果。这样,当我们在数组头部添加或删除元素时,只需要移动 start 索引,而在数组尾部添加或删除元素时,只需要移动 end 索引。
2026-01-14 16:30:39
422
原创 算法-链表双指针
这时候再来一个p2指向链表头部,p1和p2同时遍历,当p1走到末尾(走了n-k步)p2此时正好在n-k的地方,正好是倒数第k个节点。首先将每行的头放到小堆中,堆顶是整个矩阵最小的那个,然后放入哪一行的第二个元素,一次取出堆顶。先让一个指向链表头部的指针p1遍历k个位置,此时只要再走 n - k 步,p1就能走到链表。利用快慢指针,快指针一次前进两步,慢指针一次前进一步,当快指针到末尾时,慢指针到中间。和上一题几乎一样,将两个非递减数组当成矩阵的行和列,内部的元素当做对应的两个数组的和。
2026-01-13 21:40:13
1064
原创 C++新手项目——异步日志系统
lock_guard 的构造函数会立刻对 mutex_ 加锁(mutex_.lock()),在 lock 对象析构时自动解锁(RAII),因此能保证即使函数抛异常也会释放锁。与 lock_guard 不同,unique_lock 可以被传给条件变量的 wait(需要可解锁/再加锁的锁类型),所以这里使用 unique_lock 是为了配合 cond_var_.wait。在被唤醒并持有锁后检查:如果是因为系统处于关闭状态且队列已经空,直接返回 false,表示没有可供消费的数据并应终止。以追加模式打开文件。
2025-10-09 11:12:54
740
原创 C++运算符重载
允许开发者为自定义类型定义或重新定义运算符的行为,使得自定义类型的对象能够使用与内置类型相同的运算符进行操作。这不仅提高了代码的可读性,还增强了代码的表达能力。
2025-09-26 17:24:35
522
原创 std::map用法详解以及实现
std::map 是 C++ 标准模板库(STL)中的一个关联容器,用于存储键值对(key-value pairs),其中每个键都是唯一的,并且按照特定的顺序(通常是升序)自动排序。std::map 通常基于红黑树实现,提供对元素的高效查找、插入和删除操作默认情况下,std::map 使用 < 运算符对键进行排序。如果需要自定义排序方式,可以提供一个自定义的比较函数或函数对象首先需要有一个data存储键值对另外需要关乎一点如果出现两个不同的key经过哈希运算后得到相同的桶索引,这种情况成为哈希冲突。
2025-09-26 10:54:24
1043
原创 stl容器详解
在 C++ 中,迭代器 是一种用于遍历容器(如 std::vector、std::list 等)元素的对象。它们提供了类似指针的接口,使得算法可以独立于具体的容器而工作。迭代器的设计允许算法以统一的方式处理不同类型的容器。public:// 其他成员函数...这样,使用时,就能正确获取迭代器的特性。头文件默认初始化指定大小和默认值如果什么都不写等价于默认初始化使用初始化列表拷贝构造移动构造。
2025-09-19 10:57:01
831
原创 C++智能指针
有时,默认的 delete 操作不适用于所有资源管理场景。此时,可以使用自定义删除器来指定资源释放的方式。例如,管理文件句柄、网络资源或自定义清理逻辑if (fp) {fclose(fp);//// 使用 filePtr 进行文件操作\n");} // 自动关闭文件return 0;注意不能用这样的话就没法用这个自定义的删除器了第二种使用 Lambda 表达式作为删除器if(fp){fclose(fp);}//[]表示捕获的列表,()表示接受的参数。
2025-09-11 09:08:16
441
原创 C++内存管理
内存池概念新建一块内存池并分为若干份供人使用,当用户1使用完归还时放入内存池尾部/首部,避免频繁使用new或者malloc导致的开销初步思路:使用栈先进后出的思想,用完的空间归还时放在栈头注意:这里的不考虑线程安全问题假设:用户1使用空间1同时用户2使用空间2,这时需要考虑线程安全问题(使用锁)但是在内存池加锁还是在内存池上方加锁是两种设计思想//初始化列表i++) {//通过栈管理这些内存//将每个元素的地址放入了栈里面free(pool);//访问栈顶元素地址给p。
2025-09-04 11:53:13
669
原创 C++类和对象(三)
内部类就是一个类的内部再定义一个类内部的类是外部类的一个成员1.匿名对象是指没有命名的临时对象。2.它们通常在表达式中被创建,用完后马上销毁。3.匿名对象没有变量名,通常用来临时调用函数或构造对象。
2025-08-26 17:48:04
462
原创 C++日期类以及浅拷贝问题
这里先给st1初始化开辟了一个空间,假设为0x12345,当拷贝构造st2时,**st2的指针直接指向0x12345,虽然值和st1相同(因为都是同一块地址上的值)**所以当析构函数调用时,会尝试释放同一块内存,引发重复释放导致崩溃。目前完成了类的对象建立,初始化等,下一步开始进行非法日期的函数逻辑。//代码重复度高,如果增加对象比如时分秒,则要大部分改动。要实现深拷贝,就要自己写拷贝构造和运算符(复制重载)接下来要用运算符重载进行日期与日期的比较。日期减日期(两个日期相隔多少天)
2025-08-22 16:31:00
417
原创 C++—类和对象
/类里面可以定义:1成员变量,2成员方法{}int _age;class为定义类的关键字,Person为类的名字,{}内是类的主题 ,注意最后的分号。类体中内容成为类的成员,类中的变量成为类的属性或者成员变量,类中的函数称为类的方法或者成员函数。1生命和定义全部放在类体内声明和定义全部放在类体中,需注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。public://显示基本信息public://姓名char* _sex;//性别int _age;//年龄。
2025-08-18 10:24:25
766
原创 人工智能(科普向)
梯度消失:在深层神经网络中,反向传播时计算梯度时,梯度变得非常非常小,以至于接近零,激活函数(如sigmoid、tanh)在某些输入区间导数很小,层级越深,链式法则累积乘积导致梯度指数级缩小。为了一直参数的野蛮增长,采用一直损失函数减小的方法,通过增加惩罚项(利用在原用损失函数的基础之上添加参数的本身或者参数的平方和)它通过网络内部的循环连接,使得网络能够记忆之前的输入信息,从而捕捉序列中时间步之间的依赖关系。梯度:就是很多偏导数组成的向量,梯度指明了在参数空间中,损失函数增长最快的方向。
2025-08-07 08:51:25
341
原创 Python基础4
列表名.append(单个值或者列表)在末尾添加元素,如果添加的内容是列表则是把列表当成一个元素。4.列表和字符串一样,也是支持“切片操作的”规则一样,列表名【起始索引:结束索引:步长】列表名.insert(索引值, 要插入的元素)如果索引不存在,默认在最后添加。3.列表的元素也是有索引的,且索引也是从0(正向),-1(逆向)开始的。1.列表可以同时存储多个元素,可以是不同类型的,也可以是同类型的元素。列表名.extend(列表)在末尾添加元素,把列表中逐个元素添加进来。
2025-07-28 10:21:46
292
原创 python基础3
字符串变量名.find(字串,起始索引,结束索引) ------找字串在字符串中第一次出现的位置,如果写开始和结束索引(包左不包右,就在指定区间查找,找不大就返回-1)字符串变量名.rfind(字串,起始索引,结束索引) --类似于find,只不过是找字串在字符串中最后1次出现的位置。字符串变量名.rindex(字串,起始索引,结束索引)–类似于rfind,找不到就不错。字符串变量名.index(字串,起始索引,结束索引)效果同上,找不到就报错。字符变量名.replace(旧字串,新字串,替换次数)
2025-07-27 10:29:33
318
原创 Python基础2
上网案例(键盘录入自己年龄,大于十八岁可以上网,小于十八岁不可以上网)例如153 = 1x1x1+5x5x5+3x3x3。他的各个位数的立方和相加 = 它本身。while:适用于循环次数不固定。for:适用于循环次数固定。需求1:打印所有的水仙花数。需求2:统计水仙花的个数。求1-100 的偶数和。求1-100的数字和。统计思想:打印水仙花。解释:他是一个三位数。
2025-07-22 10:51:24
245
原创 python基础1
细节:无论用户输入什么数据,我们默认都会当作字符串来接受。格式:变量名 = input(‘提示信息’)输入:用户键盘输入数据,我们接收数据。2.字母和下划线组成,数字不能开头。1.要有代表的意思,见名知意。
2025-07-18 19:57:07
299
原创 C++语言—基础
1.命名空间提供一个作用域,用来封装变量、函数、类2.不同命名空间中的相同名字不会冲突3.需要使用namespace关键字,后面是命名空间的名字,使用方法就是后面接{}就可以在这个代码中有效防止了变量名字的冲突。
2025-05-13 17:41:13
1812
原创 数据结构---排序
排序方法平均情况最好情况最坏情况辅助空间稳定性冒泡排序O(n2O(n)O(n2O(1)稳定简单选择排序O(n2O(n2O(n2O(1)稳定直接插入排序O(n2O(n)O(n2O(1)稳定希尔排序O(1.3O(n2O(1)不稳定堆排序O(nlogn)O(nlogn)O(nlogn)O(1)不稳定归并排序O(nlogn)O(nlogn)O(nlogn)O(n)稳定快速排序O(nlogn)O(nlogn)O(n2O(logn-n)不稳定。
2025-05-11 13:10:56
1814
原创 下载安装使用draw.io
分别是可以添加各种种类的框图,图片的名字(我是保存在下载到drawio的那个文件夹下面了)右侧是文本的颜色,居中对齐等,矩形等形状的颜色,透明度等。如果遇到写博客的时候需要自己绘图,或者是在职场需要绘图,例如架构图,流程图,时间轴等等,都可以用到这款软件draw.io。点进进入后,根据系统不同选择不同版本安装。简单画了一下插入排序思想。
2025-04-30 10:55:04
457
原创 数据结构---二叉树与堆
开始递归并且,使k-1,知道k等于1的时候说明到了我们要计算的这层,在此之前已经,4这个节点,1已经给他返回了1,2给5返回了1,3给6返回了1,结果就是3。目前来说,使用的前序算法,第一个跟的左子树右子树的深度算过一遍之后,这个根的左子树的左子树还要去计算深度,就有点重复了,实际上就是这个根的左子树的左子树加1(加入左子树这边最深)就是这个跟的左子树深度。双亲节点或者父节点:若一个节点还有子节点,那么他就是这个节点的父节点,如上图A是B的父节点。节点的度:一个节点含有的子树的个数,如上图A的为6。
2025-04-30 09:15:12
1721
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅