- 博客(65)
- 收藏
- 关注
原创 图论----4.实现 Trie (前缀树)
计算第一个字符的索引位置,判断根节点的Trie节点数组中是否已有该字符(对应位置不为null,有Trie节点)计算第一个字符的索引位置,判断根节点的Trie节点数组是否已有该字符(对应位置不为null,有Trie节点)计算第一个字符的索引位置,判断根节点的Trie节点数组是否已有该字符(对应位置不为null,有Trie节点)计算第一个字符的索引位置,判断根节点的Trie节点数组是否已有该字符(对应位置不为null,有Trie节点)有则迭代字符与Trie节点,重复上述流程;可抽取的公共方法:(查找前缀)
2025-06-12 16:27:31
889
原创 【计组】第一章 计算机系统概述
取指:初始化状态 PC(控制器程序计数器)=0,指向主存储器存储体中的第一条指令。首先对第一条指令进行取指,将PC中存放的指令地址送到MAR(存储器地址寄存器),对内存进行寻址,并命令内存做读操作,将读取到的内容送到MDR(存储器数据寄存器)。再将MDR中的内容送至控制器的IR(指令寄存器)。分析:将IR(控制器指令寄存器)中保存的指令的操作码送至CU(控制器控制单元)进行分析,得出要执行的操作类型。执行:将IR(控制器指令寄存器)中保存的指令的地址码送至MAR(存储器地址寄存器。
2025-06-11 17:24:56
1052
原创 图论----3.课程表
操作过程中记录访问过的节点数,若出现队列为空,且未访问所有节点,则代表有环,无法完成所有课程。拓扑排序 每次选入度为0的点,然后删除这个点与其出边;再选择入度为0的点,重复上述过程。给出选修课0 ~ nC-1 先修课[a,b][c,d]... 判断是否可以完成所有课程。先将入度为0的节点入队,移除该节点并将与该节点相邻节点的入度-1。有向无环图才能进行拓扑排序,拓扑排序可能存在多种结果。先修课的先修课不能是当前课程 否则死锁。重新将入度为0的节点入队,重复上述操作。当前课程的先修课必须存在。
2025-06-11 13:14:27
107
原创 MySql----事务
事务A先查询某条不存在的记录没查到(快照读),此时事务B向数据库中插入了该条不存在的数据并提交,那么此时如果事务A还是执行正常的快照读的话仍然是不会出现幻读问题的,但如果事务A在未查到数据的情况下直接更新事务B刚刚插入的数据(当前读),那么该条被插入记录的隐藏字段DB_TRX_ID就会变成事务A的id,该行记录就对事务A的快照读也可见了。假设有事务A与事务B同时进行,事务A先查询符合条件的数据,此时事务B又插入了数量不等的符合事务A查询条件的数据,此时事务A再次查询凭空多出了符合条件的数据,即为幻读。
2025-06-10 10:46:19
1198
原创 图论----2.腐烂的橘子
初始化时维护变量 freshCount判断初始有无新鲜橘子,以及处理结束后是否还有无法被感染的橘子。首先遍历grid,将所有"腐烂的橘子"添加到队列中,记录当前队列中元素个数(区分圈层)。false代表已经全部感染或有无法被感染的,此时无需增加结果。重复上述过程知道队列为空,代表全部腐烂,每圈代表传染一次,自增记录即可。再依次取出当前队列中的元素,并将其四周的"橘子"入队,修改状态为腐烂。腐烂传染:每次腐烂的橘子会传染其四周的橘子,一共需要多少次所有橘子都腐烂。访问过的"橘子"设置为2,避免重复访问。
2025-06-10 10:36:43
113
原创 图论----1.岛屿数量
如此往复,直到四个方向全部搜索过,换到下一个节点重复该流程即可。从当前节点起,先向一个方向一直搜索,直到遇到0,更换方向。遇到"1"后搜索与其相连的"1",所有与之相连的"1"共同组成一个岛屿。岛屿: 被"0"包围的"1" 只要遇到"1"就一定至少有一个岛屿。访问过的节点重置为0,避免重复搜索。
2025-06-09 14:16:34
463
原创 场景题----数据去重
(场景提)现在有一个学生表,字段为学校、班级、姓名、语文成绩,我需要进行去重,依据为学校、班级、姓名一样就认为是同一个学生,现在丢到set里面进行去重,要怎么样实现一个去重效果?那么很容易就可以想到,我们只需要按照数据库字段创建一个与之对应的实体类,重写hashCode()与equals()后,直接将对象存入Set集合中即可自动去重。Set集合本身就无法存储重复元素,所以我们唯一需要考虑的仅仅是将对象存入Set集合时,如何让Set集合按我们需要的规则将符合条件的对象认为是相同的对象。
2025-06-08 16:58:06
1414
原创 二叉树----15.二叉树中的最大路径和
若当前节点,接收到的返回值其中一个<=0,说明其只有一个子树,或另一个子树值之 和<0废弃,当前节点与>0的返回值叠加,更新最大和向上返回即可。若当前节点,接收到的返回值均>0,则说明左右子树的值均有效,则全部叠加更新最大 值,再各自与当前节点相加,返回更大的那一个(有效根节点的筛选)。后序遍历,回溯自底向上不断筛选最佳路径。计算子树的返回值 若返回值为负直接修改为0 避免复杂的分支,可统一计算。
2025-06-08 16:31:58
1063
原创 Redis----缓存设计、旁路缓存优化
线程A进行数据更新的流程,线程A首先将进行数据库数据更新的操作,与此同时线程B查询缓存(此时缓存还没有被线程A删除),但由于某中原因缓存提前失效,线程B查询到了数据库未来得及更新的旧数据并进行重建缓存的操作,但恰好在此期间线程A更新数据库完毕并删除了缓存,线程B在线程A删除了缓存后才进行缓存重建的操作,此时多种小概率事件叠加在一起导致了数据的长期不一致,此种情况发生概率较低.可以为缓存添加有效时间,一段时间后缓存失效,自动纠错.: 将删除缓存要操作的数据添加到消息队列中,由消费者操作数据;
2025-06-07 21:14:34
2235
原创 二叉树----14.二叉树的最近公共祖先
则说明另一个节点在别的方向或当前目标节点为另一个目标节点的父节 点直接返回即可。则说明另一个节点未找到或都在left的子树中;返回left即可,反之返回right。则说明两目标节点在当前节点两侧;若当前节点为目标节点之一:(已包含在终止条件中)后序遍历先找到目标节点,再回溯逐层向上返回。找到给定节点 p q 的最近公共祖先。
2025-06-07 21:08:41
1143
原创 二叉树----13.路径总和 III
判断哈希表中存在几个值为 当前前缀和 - target 的元素 有几个即为几条路径 同560.和为k的子数组。将当前 前缀和添加到哈希表中(查询前添加 避免当前前缀影响结果)遍历二叉树的同时,计算每个节点对应的前缀和。递归遍历 左子树 与右子树。求和为指定值的路径条数,且由上自下遍历。不涉及到对根节点的处理 遍历顺序无所谓。
2025-06-07 21:06:43
1116
原创 Redis----内存回收
Redis主从模式,从节点不会主动改变自身保存的数据,即使是key过期了也不会主动清除,而是依靠主节点当key过期时在AOF文件中追加一条del语句,发送给从节点执行。设置了过期时间的key会在Expires中再储存一份,判断其是否过期,只需要查询 Expires中对应key的过期时间与当前时间进行对比。volatile-ttl: 淘汰设置了ttl的key,优先淘汰剩余时间更短的key。volatile-ttl: 淘汰设置了ttl的key,优先淘汰剩余时间更短的key。
2025-06-05 19:33:49
2016
原创 二叉树----12.从前序与中序遍历序列构造二叉树
再从中序序列中定位根节点 两侧即为左右子树的节点。由先序(第一个)或后序(最后一个)确定根节点。2.在中序遍历的数组中找到根节点,根节点两侧的元素即为二叉树的左子树与右子树。中序序列必备 先序,后序序列任意。先序遍历(根 左 右) 与 中序遍历(左 根 右)的顺序 构建二叉树。3.被分割的子数组 两侧第一个元素即为子树的根节点 重复上述流程即可。重复上述流程 递归构建即可。1.由先序遍历确定根节点(数组第一个元素) 创建节点实例。
2025-06-05 19:27:22
1033
原创 Redis----集群
什么是脑裂: 在Redis一主多从的主从架构中,因为某些原因主节点的网络出现问题, 与所有从节点以及哨兵失去连接,但唯独与客户端的连接保持正常,仍然在处理客户端的请求,由于失联主节点是无法与从节点进行数据同步的;:若主从节点之间的连接由于网络故障导致连接断开,再次连接时就会进行增量同步,依据offset截取未同步的命令,缓冲区是环形的,若写满会覆盖掉原有的数据,当再次连接时若从节点还未同步的命令被新的数据覆盖(依据两者的offset判断),则有数据无法通过增量同步的方式同步,需要重新进行全量同步.
2025-06-04 19:16:06
2204
原创 二叉树----11.二叉树展开为链表
即左子树与右子树的连接点为先序遍历顺序下左子树的最后一个节点(即根节点第一个左子节点最深的右子节点)最终所有节点都按先序遍历的顺序挂在根节点的右子树上,不断将每个节点的左子树合并到右子树上即可。1.找到当前节点的左子节点(定位到要合并的左子树) 不存在左子节点 则直接移动到右子节点即可。3.链接左子树与右子树,再将链接后的子树变更为根节点的右子树。即 链表顺序为 根节点-> 左子树所有节点(同样根左右)-> 右子树所有节点(同样根节点)4.迭代到新的右子节点(原树的左子节点)合并的同时保证先序遍历的顺序;
2025-06-04 18:17:15
1126
原创 二叉树----10.二叉树的右视图
按先左后右的顺序入队 每层可见的元素必然是队尾元素,只保存每层队尾元素 其余直接移除即可。右子树外侧 > 右子树内侧 > 左子树内侧 > 左子树外侧;没层递归访问到的第一个元素就是最右侧的元素。层序遍历(引入队列) + 优先级限制。按根 右 左的顺序递归遍历。高优先级节点出现后,低优先级的节点不可见。从顶部开始按层级输出。
2025-06-03 16:55:24
1283
原创 Redis----线程模型与持久化
基于内存操作:Redis速度快的直接原因是因为其是基于内存的,绝大多操作都是在内存中之直接进行的,速度极快,可以用一个线程处理众多客户端请求而不会出现性能瓶颈,而且还可以避免并发问题,不存在线程切换带来的额外性能消耗。底层数据结构优化:Redis还对底层数据结构做了许多优化 比如String有三种编码方式在不同的情况下采用不同的编码方式减少内存空间申请次数,避免出现内存碎片,如渐进式rehash在扩容时不会阻塞。
2025-06-02 23:10:13
2027
原创 二叉树----9.二叉搜索树中第K小的元素
利用中序遍历 遍历二叉搜索树,遍历顺序即为元素递增顺序。第k小的元素,即为中序遍历,遍历到的第k个元素。
2025-06-02 22:52:28
1041
原创 二叉树----8.验证二叉搜索树
中序遍历: 左 中 右;遍历顺序完美符合,二叉搜索树的递增规律。左子树只包含小于当前节点的数。右子树只包含大于当前节点的数。
2025-06-01 23:48:27
1047
原创 二叉树----7.将有序数组转换为二叉搜索树
左子树:左半部分的中间节点 右子树: 右边部分的中间节点。根节点: 整个数组的中间节点,此时数组一分为二。以此类推 直到整个数组转化完毕为止。转化方式: 不断从中间均分数组。
2025-06-01 00:44:06
972
原创 Redis----五种常见数据类型
EMBSTR,当SDS存储的内存空间小于等于44字节(此时RedisObject刚好不大于64 字节) 采用EMBSTR编码方式,该编码方式会直接申请一块连续的内存空间存储,RedisObject与SDS 因为Redis底层申请内存时都是申请2的n次方的大小,此时占用的内存空间不大于64字节,可以轻易申请到一片连续的内存空间减少内存申请次数,且不易产生内存碎片,减少花在申请内存上的额外性能开销。Hash与ZSet非常类似,Hash只有键值存储的需求,无排序需求,底层采用Dict或ZipList实现即可。
2025-05-31 00:07:15
1958
原创 二叉树----6.二叉树的层序遍历
引入队列,将节点保存到队列中, 弹出节点时将该节点的子节点入队。二叉树这个数据结构本身无法做到按层级遍历。层级区分: 提前记录队列中元素个数。
2025-05-30 14:50:28
994
原创 二叉树----5.二叉树的直径
直径:以某点为基准 其左子树最大深度+右子树最大深度。计算每个节点的左右子树最大深度,顺带计算直径即可。该二叉树直径: 所有直径中最长的一个。
2025-05-29 12:32:15
1039
原创 Redis----数据结构
一款基于内存的非关系型数据库,对数据的读写操作都是在内存中完成的,具有高性能 高并发的特点,可以用来作为缓存降低mysql数据库的压力,还可以用来做分布式锁 以及轻量级消息队列等。
2025-05-28 11:42:56
2406
原创 二叉树----4.对称二叉树
外侧与外侧比较---> 左子树的左节点 与 右子树的右节点。内侧与内侧比较---> 左子树的右节点 与 左子树的左节点。是否对称---> 左右子树各自反转后是否相等。
2025-05-28 09:38:38
1072
原创 二叉树----2.二叉树的最大深度
左子树or右子树 遍历到底部 逐层返回高度++ 最大的那个即为最大深度。根节点的高度即为二叉树的最大深度 利用后序遍历即可解决。
2025-05-27 00:30:33
1006
原创 链表----14.LRU缓存
操作双向链表中节点时间复杂度也是O(1)的关键: 哈希表中直接存储链表中节点 先在hash表中直接定位到元素O(1) 再操作即可。头节点:最近访问的元素 尾节点:最久未访问的元素。若达到上限 定位到最久未访问的元素(双向链表尾节点)删除再添加即可 O(1)即 双向链表维护各元素访问顺序,哈希表存储双向链表中的节点 两者搭配使用即可满足需求。添加元素:若未达到上限 将元素添加到双向链表头节点,以及哈希表中即可。访问元素:利用哈希表直接访问O(1) 再将元素移动到头节点即可。移动节点到头部(先删除再重新添加)
2025-05-27 00:27:01
2007
原创 链表----13.合并 K 个升序链表
分解: 将k个链表二分,对分出来的两组继续二分,直到无法再细分。合并: 对每组的两个链表直接合并 一个则直接返回。回溯: 自顶向上逐层合并 直到全部合并。分治: 分解 合并 回溯。
2025-05-27 00:24:57
969
原创 链表----12. 排序链表
核心:将链表拆分至最小单元时 单个节点必然是有序的 此时做合并操作,合并过程保证有序;至此有序性“自顶向下传递”首先不断将链表从中间节点拆分,直到拆分到最小单元 单个节点必然可视为有序,此时再不断回溯做合并操作。自顶向下的归并排序 拆分链表 + 两有序链表合并 + 递归。
2025-05-27 00:23:10
984
原创 链表----10.K 个一组翻转链表
无法直接写死反转逻辑;引入反转链表依次反转的方式;同时添加额外的指针控制组间边界,以及组之间的重新链接。额外指针Start:当前组第一个节点 prevTail:上一组最后一个节点(初始化为dummy) bndPtr:控制组间边界。dummy:简化交换 保留头节点 prev:前驱 利用他交换后两个节点 temp:临时保存确保正常交换。两两交换链表中节点: dummy prev temp1 temp2。反转链表: 利用 pre temp curr 三个指针依次进行反转。反转链表与两两交换链表中节点的结合。
2025-05-27 00:19:08
1178
原创 链表----9.两两交换链表中的节点
两两交换: 指针重定向 两两一组,利用该组的前一个节点进行操作。奇数个节点: dummy.next.next == null。偶数个节点: dummy.next == null。引入虚拟头节点 便于操作头节点 以及 保留头节点。
2025-05-27 00:15:38
1016
原创 链表----8.删除链表的倒数第 N 个结点
结论:快慢指针从虚拟头节点开始 快指针先移动n+1个节点 快慢指针再一起移动 当快指针指向null时 慢指针指向目标节点的上一个节点。特殊情况:目标节点即为头节点,快指针在初始化时就已经指向了null 此时慢指针无需移动 直接删除即可。核心: 定位到目标节点的上一个节点 令node.next = node.next.next 即可。快慢指针 + 虚拟头节点。
2025-05-27 00:12:16
1185
原创 链表----7.两数相加
从头节点依次相加无需考虑位数对齐 便于进位 相较于顺序更为简遍。创建哨兵节点 便于操作以及保留头节点。逆序存储与逆序相加的意义。
2025-05-27 00:07:37
1021
原创 链表----6.合并两个有序链表
比对两指针value 保存较小的,保存后迭代对应的指针 如此循环往复。双指针 遍历两个链表 定义一个新节点 保存新的链表。利用一个额外节点保存头节点 避免合并过程中起点丢失。
2025-05-27 00:06:04
1087
原创 链表----5.环形链表 II
利用快慢指针解决 快指针两步/次 慢指针一步/次 相对速度为1 快指针必然和慢指针相遇,不会跳过慢指针。结论: 当快慢指针在环内相遇时 再从起点出发一个慢指针 两慢指针相遇点必然是环入口点。引入hash表第一次出现重复的节点就是环的入口。不仅仅是判断是否是环形链表,还需要返回入口。
2025-05-27 00:04:34
995
原创 链表----4.环形链表
每读取到一个节点 判断其在hash表中是否已经存在 存在则说明是环形链表。快慢指针 两个指针一起遍历链表 一个速度快 一个速度慢。引入一个hash表 遍历过程中将节点存入其中。若是环形 则必然会在某个节点相遇(即被套圈)
2025-05-27 00:00:24
1112
原创 链表----3.回文链表
反转后半部分 前半部分与反转后的后段相同 则是回文链表。回文链表: 对称 前后两部分镜像。先遍历链表得到长度 定位对称点。
2025-05-26 23:57:35
1005
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人