- 博客(120)
- 收藏
- 关注
原创 160. 相交链表
本文介绍了寻找两个单链表相交节点的两种方法。方法1使用数组存储节点值,通过反向遍历比较,但时空复杂度均为O(m+n)。方法2采用双指针技巧,让两个指针分别遍历两个链表后交换遍历路径,最终会在相交点相遇或同时到达NULL。这种方法时间复杂度为O(m+n),空间复杂度仅为O(1),是最优解。算法通过消除链表长度差的影响,确保在最多遍历两遍链表的情况下找到相交节点或确认无交点。
2026-05-17 22:23:36
354
原创 3. 无重复字符的最长子串
本文介绍了一种使用滑动窗口算法求解无重复字符最长子串长度的方法。通过维护一个哈希集合记录窗口内的字符,用左右指针动态调整窗口边界。当遇到重复字符时移动左指针缩小窗口,否则扩展右指针。算法在O(n)时间内高效解决问题,空间复杂度为O(k)。代码实现清晰,通过维护当前窗口长度和全局最大值,最终返回最长无重复子串的长度。
2026-05-16 22:35:38
230
原创 287. 寻找重复数
本文介绍了一种使用Floyd判圈算法在数组中寻找重复数字的方法。给定一个长度为n+1的数组,其中数字范围在[1,n]内,且只有一个重复数字。算法将数组视为链表,利用快慢指针检测环的存在:慢指针每次移动一步,快指针每次移动两步,当两者相遇时重置快指针为起点,然后两者同步移动,再次相遇点即为环入口,对应重复数字。该算法时间复杂度O(n),空间复杂度O(1),无需修改原数组。通过将数组值视为指针,重复数字必然形成环,环入口即为所求重复值。
2026-05-15 22:26:56
220
原创 72. 编辑距离
本文介绍了使用动态规划求解字符串编辑距离问题。通过构建二维DP数组,其中dp[i][j]表示将word1前i个字符转换为word2前j个字符所需的最少操作次数。算法处理三种操作(插入、删除、替换)的情况,当字符相同时直接继承前驱状态,不同时取替换、删除和插入操作中的最小值加1。最终返回dp[len1][len2]作为结果,时间复杂度和空间复杂度均为O(n²)。示例展示了如何计算"horse"到"ros"的最少3次操作过程。
2026-05-14 21:41:19
346
原创 1143. 最长公共子序列
本文介绍了使用动态规划求解最长公共子序列(LCS)问题的方法。通过构建二维dp数组,其中dp[i][j]表示text1前i个字符和text2前j个字符的LCS长度。当字符匹配时,状态转移为dp[i+1][j+1]=dp[i][j]+1;否则取dp[i+1][j]和dp[i][j+1]中的较大值。算法通过双重循环遍历两个字符串,最终返回dp[m][n]作为结果,时间复杂度为O(mn)。这种方法有效地解决了在不改变字符顺序情况下寻找两个字符串最长公共子序列的问题。
2026-05-12 22:21:06
228
原创 5. 最长回文子串
本文介绍了使用中心扩展法求解最长回文子串的算法。该算法通过遍历字符串中的每个字符作为回文中心,分别处理奇数长度和偶数长度的回文串情况。在扩展过程中不断比较左右字符,更新最长回文长度和起始位置。算法时间复杂度为O(n²),空间复杂度为O(1),最后通过substr截取并返回最长回文子串。
2026-05-11 22:52:11
290
原创 64. 最小路径和
本文介绍了一个使用动态规划求解二维网格最小路径和问题的算法。给定一个m×n的非负整数网格,每次只能向右或向下移动,要求从左上角到右下角的最小路径和。算法通过原地修改网格数组实现:首先处理第一行和第一列的边界情况,然后逐个计算每个位置的最小路径和(取上方或左方较小值加上当前值)。最终右下角元素即为所求最小路径和。该算法时间复杂度为O(mn),空间复杂度为O(1)。示例展示了算法在具体输入下的执行过程和结果。
2026-05-10 21:49:45
206
原创 62. 不同路径
本文介绍了一个机器人从m×n网格左上角移动到右下角的不同路径数问题。采用动态规划方法,初始化第一行和第一列为1,状态转移方程为dp[i][j] = dp[i-1][j] + dp[i][j-1],表示当前位置路径数等于上方和左方路径数之和。通过双重循环填充DP表,最终返回dp[m][n]即为总路径数。时间复杂度O(mn),空间复杂度O(mn)。
2026-05-09 22:08:52
243
原创 彻底搞懂进程源语!Linux 进程通信与同步核心基石
摘要:本文详细介绍了Linux进程管理的核心概念和系统调用。重点讲解了fork()创建进程的机制,包括父子进程执行流程、返回值差异以及循环创建多进程的实现方法。同时阐述了新版fork采用的写时复制(COW)技术原理,对比分析了vfork的优缺点。此外,还介绍了execl函数实现进程重载的技术细节,以及wait/waitpid对僵尸进程的回收机制,包括阻塞和非阻塞两种处理方式。通过多个实践案例展示了进程创建、任务分离、资源回收等关键操作的具体实现方法。
2026-04-26 22:00:05
590
原创 763. 划分字母区间
这篇文章介绍了一种贪心算法来解决字符串划分问题,要求将字符串划分为尽可能多的片段,且同一字母只能出现在一个片段中。算法步骤如下: 首先遍历字符串,记录每个字符最后出现的位置(右边界) 再次遍历字符串,维护当前片段的右边界最大值 当遍历位置等于当前最大右边界时,说明找到一个分割点,记录当前片段长度并重置计数器 该算法通过两次遍历实现了最优划分,时间复杂度O(n),空间复杂度O(1)(使用固定大小的数组存储字符位置)。示例输入"ababcbacadefegdehijhklij"被正确划分为[
2026-04-26 21:51:58
179
原创 看不懂、写不出正则?这篇彻底打通你的正则思维
正则表达式是一种用于数据处理的强大工具,支持模糊查询、格式验证等操作。相比普通字符串操作,正则使用贪心算法实现更高效的模糊匹配。主要元字符包括*(0次或多次)、+(1次或多次)、.(任意字符)、[](字符集)等,使用时需注意转义。正则支持贪婪和非贪婪两种匹配模式,前者效率更高。在Linux中可通过grep等命令使用正则,在程序中需包含regex.h头文件并使用regcomp、regexec等函数。实际应用中,正则表达式常用于验证手机号、邮箱等格式,匹配HTML超链接等场景。使用时数据规则越清晰,匹配效果越好
2026-04-25 22:12:19
692
原创 45. 跳跃游戏 II
本文介绍了使用贪心算法解决跳跃游戏II问题,目标是找到从数组起点到终点的最小跳跃次数。算法通过维护当前可到达的区间[left, right],在每次跳跃时计算该区间内所有位置能到达的最远距离farthest,然后将区间更新为[right+1, farthest],同时跳跃次数加1。当右边界覆盖终点时终止循环,返回最小跳跃次数。该算法通过类似BFS的方式层层推进,时间复杂度为O(n),空间复杂度为O(1),相比DFS枚举所有方案更高效。代码中已标注关键步骤,并附有原理图说明区间更新过程。
2026-04-25 21:55:41
228
原创 掌握这些 Git 技巧,开发效率直接翻倍
版本控制是Git的核心功能,它允许记录文件的变化历史,方便回溯和协作。Git采用分布式架构,每个开发者拥有完整的仓库副本,不依赖中央服务器。初始化仓库使用git init命令,克隆现有仓库用git clone <url>。工作区、暂存区和版本库构成Git的三棵树结构,修改文件后需通过git add和git commit提交变更。
2026-04-24 22:02:16
821
原创 55. 跳跃游戏
摘要: 题目要求判断能否从数组起点跳跃到最后一个下标。采用反向贪心算法,从数组末尾倒序遍历,检查当前位置能否到达当前目标位置(初始为末尾)。若i+nums[i]≥target,则更新目标为i。最终若目标位置回退到起点(0),返回true,否则false。时间复杂度O(n),空间复杂度O(1)。示例中[2,3,1,1,4]可达,而[3,2,1,0,4]因下标3的0无法跨越而失败。
2026-04-24 21:50:02
50
原创 215. 数组中的第K个最大元素
这篇文章介绍了一个算法题解:如何在数组中找到第K个最大的元素。文章提供了三种解决方案: 堆排序法:直接排序后取第K大的元素,时间复杂度O(nlogn) 堆维护法:维护一个大小为K的小顶堆,遍历数组更新堆,时间复杂度O(nlogk) 快速选择法:基于快速排序的分区思想,随机选择pivot将数组分为三部分,递归处理。平均时间复杂度O(n),最坏情况O(n²) 其中重点介绍了快速选择算法,通过随机选择基准值将数组划分为大于、等于和小于基准值三部分,根据K值的位置决定递归处理哪一部分,直到找到第K大的元素。这种方法
2026-04-23 10:56:41
253
原创 240. 搜索二维矩阵 II
摘要: 题目要求在具有行列有序特性的二维矩阵中高效搜索目标值。矩阵每行从左到右、每列从上到下均为升序排列。采用从右上角开始的搜索策略:若目标值小于当前元素,则左移一列;若大于当前元素,则下移一行。该算法时间复杂度为O(m+n),优于暴力遍历(O(mn))和逐行二分查找(O(mlogn))。图示和代码展示了如何通过逐步缩小搜索范围快速定位目标值。
2026-04-22 21:42:32
181
原创 别再烂写网络服务!Epoll + 线程池才是高性能标准答案
本文介绍了一个基于Linux C语言实现的高并发网络服务器项目,采用epoll I/O多路复用、线程池和生产者-消费者模型架构。项目核心包括:1) epoll事件驱动模块,实现高效的网络I/O处理;2) 线程池与任务调度模块,动态管理线程资源;3) 业务处理模块,完成客户端连接和数据交互。系统通过epoll监听事件、线程池处理任务的方式实现高并发连接处理,支持动态线程调整和任务队列管理。该项目展现了Linux下高性能服务器开发的关键技术,包括非阻塞I/O、事件驱动、多线程协同等核心概念。
2026-04-22 21:02:49
745
原创 153. 寻找旋转排序数组中的最小值
本文介绍了在旋转排序数组中寻找最小值的二分查找算法。原数组升序排列后经多次旋转形成两个有序子数组,最小值位于分界点。算法通过比较中点与左右指针的值,判断有序区间并逐步缩小搜索范围:若中点值大于左指针值,最小值在右侧;否则在左侧。时间复杂度为O(logn),优于暴力遍历。代码示例展示了如何实现这一过程,适用于元素互不相同的旋转数组。
2026-04-21 22:04:50
169
原创 33. 搜索旋转排序数组
这篇文章介绍了在旋转排序数组中查找目标值的二分查找算法。原理解释指出:虽然可以直接遍历数组(O(n)时间复杂度),但更优解是采用二分查找(O(log n))。算法通过判断中点所在区间(左/右有序区间)和target的位置关系,动态调整搜索边界。关键点在于先确定中点落在哪个有序区间,再根据target与该区间的关系决定搜索方向。该方法充分利用了旋转数组部分有序的特性,通过二分策略高效定位目标值。文末附有原理示意图和详细注释的C++代码实现。
2026-04-17 22:03:25
186
原创 34. 在排序数组中查找元素的第一个和最后一个位置
摘要 该题目要求在有序数组中查找目标值的起始和结束位置,若不存在则返回[-1,-1]。解法采用二分查找,时间复杂度为O(log n)。通过两次二分查找分别定位左右边界:查找左边界时在找到目标值后继续向左搜索,右边界则向右搜索。核心在于处理中间值等于目标值时,根据查找方向调整搜索范围。示例代码展示了这一实现,通过isLeft参数区分左右边界查找,确保高效定位目标值范围。
2026-04-16 21:44:15
51
原创 74. 搜索二维矩阵
本文介绍了一种在二维矩阵中高效搜索目标值的方法。题目给定一个满足特定排序条件的m×n整数矩阵,要求判断目标值是否存在。解决方案将二维矩阵视为一维数组进行二分查找,通过映射关系(row=mid/n,col=mid%n)定位元素位置。算法时间复杂度为O(log(m×n)),空间复杂度为O(1)。代码实现先处理空矩阵情况,然后通过二分查找不断缩小范围,最终确定目标值是否存在。这种方法避免了额外空间使用,充分利用矩阵的排序特性实现高效搜索。
2026-04-15 21:58:40
325
原创 208. 实现 Trie (前缀树)
本文介绍了Trie(前缀树)的实现原理及其核心操作。前缀树是一种用于高效存储和检索字符串的数据结构,支持插入、查找和前缀匹配功能。文章详细解释了TrieNode节点结构和Trie类的实现,包括insert()、search()和startsWith()三个关键方法的算法步骤。insert()方法通过逐个字符构建树结构并标记单词结尾;search()方法检查完整单词是否存在;startsWith()方法判断是否存在指定前缀。该实现使用哈希表存储子节点,能够高效处理字符串的存储和查询操作,适用于自动补全、拼写检
2026-04-14 22:13:20
371
原创 207. 课程表
这篇文章介绍了如何通过拓扑排序和广度优先搜索(BFS)来判断课程安排的可行性。题目给定课程数量和先修条件,要求判断是否能完成所有课程学习。关键点在于检测有向图中是否存在环:若存在环则无法完成,否则可以完成。 算法步骤如下: 构建入度数组和邻接表表示课程依赖关系 将入度为0的课程加入队列 进行BFS遍历,每次修完课程后更新后续课程的入度 若入度减为0则加入队列 最终比较已修课程数与总课程数 该方法通过拓扑排序有效检测环的存在,时间复杂度为O(V+E),其中V是课程数,E是先修条件数。
2026-04-10 21:30:15
366
原创 994. 腐烂的橘子
摘要:本文介绍了使用BFS算法解决"腐烂的橘子"问题。给定一个m×n网格,其中0表示空格,1表示新鲜橘子,2表示腐烂橘子。每分钟腐烂橘子会使相邻4个方向的新鲜橘子腐烂。算法首先统计新鲜橘子数量,并将所有腐烂橘子坐标存入队列。通过BFS逐层遍历,每轮代表1分钟,将相邻新鲜橘子标记为腐烂并减少计数。若队列为空后仍有新鲜橘子,返回-1;否则返回总时间。该方法能有效模拟橘子腐烂过程并计算最小时间。
2026-04-09 21:54:52
161
原创 131. 分割回文串
本文介绍了一种使用回溯算法分割字符串为回文子串的解决方案。通过递归遍历字符串,每次选取可能的回文子串,当遍历到字符串末尾时将当前分割方案存入结果。关键点在于:1) 使用双指针法判断子串是否为回文;2) 通过回溯机制(push/pop操作)实现路径复用。该算法时间复杂度为O(n*2^n),空间复杂度为O(n),适用于长度≤16的字符串。示例展示了如何将"aab"分割为[["a","a","b"],["aa",&
2026-04-08 22:03:31
57
原创 79. 单词搜索
这篇文章介绍了一个使用回溯算法解决单词搜索问题的方案。给定一个二维字符网格和一个目标单词,需要判断是否能通过相邻单元格(上下左右)的字母顺序连接出该单词,且每个单元格只能使用一次。 解决方案采用深度优先搜索(DFS)算法,核心思路是从网格的每个格子出发,递归搜索四个方向: 检查当前字符是否匹配单词对应位置 标记当前格子为已访问 向四个方向继续搜索下一个字符 若匹配失败则回溯,撤销标记 算法通过递归遍历所有可能的路径,只要找到一条完整匹配单词的路径就返回true,否则返回false。关键点在于处理边界条件、字
2026-04-07 22:33:01
261
原创 22. 括号生成
本文探讨了使用回溯算法生成有效括号组合的问题。通过递归深度优先搜索,在满足左括号数不超过n且右括号数不超过左括号数的条件下,逐步构建合法括号组合。算法采用剪枝策略优化搜索过程:当左括号数小于n时添加左括号;当右括号数小于左括号数时添加右括号。当左右括号数均达到n时,将当前组合存入结果。时间复杂度为O(4^n/√n),空间复杂度为O(n)用于递归栈。该方法高效地生成了所有可能的有效括号组合。
2026-04-06 22:04:26
51
原创 39. 组合总和
摘要: 本文解决组合总和问题,给定无重复元素的整数数组candidates和目标值target,找出所有和为target的组合(元素可重复使用)。采用回溯+剪枝算法:通过递归枚举可能组合,当目标值减为0时保存结果,小于0时回溯。关键剪枝策略是使用start参数控制遍历起点,避免重复组合。每次递归后撤销最后选择(回溯)以尝试其他可能性。例如,candidates=[2,3,6,7], target=7时,输出[[2,2,3],[7]]。算法保证高效性,组合数少于150个。
2026-04-04 19:11:05
230
原创 17. 电话号码的字母组合
本文解决电话号码字母组合问题,给定数字字符串返回所有可能的字母组合。通过深度优先搜索(DFS)回溯算法实现:1)建立数字到字母的映射表;2)递归处理每个数字,依次选择对应字母进行组合;3)当组合长度等于输入数字串长度时保存结果。关键点在于递归中维护临时字符串,完成组合后回溯撤销选择。该算法时间复杂度为O(3^N×4^M),其中N/M分别对应3/4字母的数字个数,空间复杂度为O(N)用于递归栈。示例输入"23"输出["ad","ae","a
2026-04-03 21:49:15
224
原创 78. 子集
摘要 该文介绍了使用回溯算法求解子集问题的方法。给定一个不含重复元素的整数数组,要求返回所有可能的子集。算法采用深度优先搜索(DFS)策略,通过递归实现回溯过程。关键点在于:每次递归都有两种选择 - 包含当前元素或不包含当前元素,通过临时数组tmp记录当前路径状态,当路径长度等于原数组长度时保存结果。时间复杂度为O(2^n),因为n个元素的集合有2^n个子集。文中提供了C++实现代码和决策树示意图,清晰地展示了回溯算法的执行流程。
2026-04-02 22:26:51
64
原创 739. 每日温度
本文介绍了求解每日温度问题的两种方法。给定温度数组,要求返回每个位置下一个更高温度出现的天数差。方法1采用双重循环暴力解法,时间复杂度O(n²)。方法2使用单调栈优化,维护一个存储下标的递减栈,当遇到更高温度时计算天数差并弹出栈顶,时间复杂度O(n)。代码实现了单调栈解法,通过栈顶比较和下标差值计算来高效解决问题,适用于大规模数据。图示展示了两种方法的处理流程,突出单调栈在时间效率上的优势。
2026-04-01 21:51:08
235
原创 394. 字符串解码
本文介绍了一种使用栈结构解码嵌套字符串的算法。题目要求将形如"k[encoded_string]"的编码字符串解码为重复k次的字符串。算法通过维护一个字符串栈,遍历输入字符串:遇到非右括号字符时压栈;遇到右括号时,依次弹出字符拼接直到左括号,再弹出数字计算重复次数,将重复后的字符串重新压栈。最后将栈中所有字符串拼接得到最终结果。该算法能正确处理多层嵌套的编码字符串(如"3[a2[c]]"转为"accaccacc"),时间复杂度为O(n),适用于长度
2026-03-31 22:03:41
174
原创 416. 分割等和子集
本文探讨了如何判断一个正整数数组能否分割成两个元素和相等的子集。核心思路是:首先计算数组总和,若为奇数则直接返回false;若为偶数则将其一半作为目标值。采用动态规划方法,定义dp数组记录各和值的可达性,通过遍历数组元素逐步更新dp状态。若最终达到目标值则返回true。该方法通过将问题转化为子集和问题,利用动态规划有效降低了时间复杂度,适用于数组规模在200以内的情况。代码实现中使用了辅助数组避免状态覆盖,并设置了提前终止条件优化性能。
2026-03-30 21:56:06
67
原创 152. 乘积最大子数组
给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续 子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。nums 的任何子数组的乘积都 保证 是一个 32-位 整数。请注意,一个只包含一个元素的数组的乘积是这个元素的值。解释: 子数组 [2,3] 有最大乘积 6。输入: nums = [2,3,-2,4]输入: nums = [-2,0,-1]测试用例的答案是一个 32-位 整数。
2026-03-24 22:32:57
51
原创 300. 最长递增子序列
例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。若 nums[i] > nums[j],说明 nums[i] 可以接在以 nums[j] 结尾的递增子序列后面;此时 dp[i] = max(dp[i], dp[j] + 1)(取所有符合条件的最大值);解释:最长递增子序列是 [2,3,7,101],因此长度为 4。输入:nums = [10,9,2,5,3,7,101,18]输入:nums = [7,7,7,7,7,7,7]输入:nums = [0,1,0,3,2,3]
2026-03-23 22:32:34
223
原创 139. 单词拆分
④遍历curlevel查看是否有与目标一样的串,有返回true,否则遍历字典并与curlevel中的串拼接,符合拼接的字符串小于等于目标并且拼接的是目标的前缀加入nextlevel。输入: s = “catsandog”, wordDict = [“cats”, “dog”, “sand”, “and”, “cat”]如果可以利用字典中出现的一个或多个单词拼接出 s 则返回 true。解释: 返回 true 因为 “applepenapple” 可以由 “apple” “pen” “apple” 拼接成。
2026-03-19 22:20:02
231
原创 108. 将有序数组转换为二叉搜索树
2、取中间值:用 left + (right-left)/2 而非 (left+right)/2,避免整数溢出。1、递归终止条件:left > right 说明当前区间无元素,返回空节点。解释:[1,null,3] 和 [3,1] 都是高度平衡二叉搜索树。输入:nums = [-10,-3,0,5,9]右区间 [mid+1, right] → 右子树。左区间 [left, mid-1] → 左子树。输出:[0,-3,9,-10,null,5]nums 按 严格递增 顺序排列。输入:nums = [1,3]
2026-03-14 22:32:24
62
原创 322. 零钱兑换
→i 的顺序算的,所以 dp[i - coins[j]] 早就被算完并存在数组里了,是确定的 “历史最优解”。dp[i - coins[j]]:已经计算完成的历史值(比如凑 6 元、9 元、10 元的最少硬币数),是确定的、不会再变的。dp[i]:当前正在计算的目标值(比如凑 11 元的最少硬币数),一开始是初始值(比如 12),会被不断更新;计算 dp[i] 时,i - coins[j] 一定是小于 i 的数(因为 coins[j] ≥ 1);输入:coins = [1], amount = 0。
2026-03-12 21:29:48
46
原创 279. 完全平方数
状态转移:对于每个数 i,遍历所有小于等于 i 的完全平方数 j²,则 dp[i] = min(dp[i], dp[i - j²] + 1)(+1 表示选了 j² 这个数)。其他 dp[i] 初始化为一个较大值(比如 i,因为最坏情况是用 i 个 1 组成)。状态定义:定义 dp[i] 表示和为 i 的完全平方数的最少数量。给你一个整数 n ,返回 和为 n 的完全平方数的最少数量。初始状态:dp[0] = 0(和为 0 不需要任何数);解释:12 = 4 + 4 + 4。解释:13 = 4 + 9。
2026-03-10 11:32:20
66
原创 198. 打家劫舍
解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。如果偷第 i 间,那么第 i-1 间就不能偷,总金额 = 第 i 间金额 + 前 i-2 间的最大金额。状态转移方程:dp[i] = max(dp[i-1], dp[i-2] + nums[i])解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
2026-03-09 22:27:33
55
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅