承接上一篇内容,继续为大家拆解全栈开发高频算法类名词,保持一贯的风格——不搞晦涩定义,只讲“是什么、用在哪、避坑点”,结合开发实战场景,穿插插图辅助理解,全程无AI套话,确保新手能看懂、老开发者能查漏补缺,稳步补全70个算法,助力大家提升代码效率、应对面试难点。
进阶提升(30个,中级,提升代码效率)
掌握这30个算法,能解决工作中80%的复杂场景,比如前端虚拟列表、后端海量数据处理、接口优化,也是面试中高频考察的内容,比基础算法更实用,更能拉开和新手的差距。
16. 双指针(Two Pointers)
人话解读:算法界的“效率神器”,核心是“用两个指针(索引),分别指向数据的不同位置,根据条件移动指针,不用额外开辟空间”,就像两个人一起走路,一个走得快,一个走得慢,或者一个从左走,一个从右走,配合完成任务。
前后端场景:前端用在数组去重、回文串判断(比如判断手机号是否是回文)、虚拟列表滚动定位;后端用在链表操作(判断链表是否有环、找链表中间节点)、数组合并(合并两个有序数组)、海量数据筛选。
老炮踩坑提醒:新手容易出现“指针越界”问题,比如左右指针移动时,没判断边界,导致数组下标越界报错;记住:移动指针前,一定要判断指针是否在合法范围内(比如左指针小于右指针)。
17. 滑动窗口(Sliding Window)
人话解读:核心是“用一个‘窗口’(连续的子数组/子字符串),在数据中滑动,动态调整窗口大小,找到符合条件的窗口”,就像用一个放大镜,在一张纸上滑动,放大不同的区域,找到需要的内容。
前后端场景:前端用在字符串匹配(比如查找最长不含重复字符的子串)、列表筛选(比如筛选连续的符合条件的商品);后端用在接口限流(比如1分钟内最多允许100个请求,用滑动窗口统计请求数)、海量数据连续筛选(比如筛选连续7天活跃的用户)。
老炮踩坑提醒:新手容易固定窗口大小,导致无法找到最优解;记住:滑动窗口可以是固定大小,也可以是动态大小,根据场景选择,比如接口限流用固定大小,字符串匹配用动态大小。
18. 动态规划(Dynamic Programming,DP)
人话解读:听起来很高大上,其实核心是“拆分问题、缓存结果”,把一个复杂的大问题,拆分成多个相似的小问题,解决每个小问题后,把结果缓存起来,避免重复计算。就像算斐波那契数列,f(5)=f(4)+f(3),f(4)=f(3)+f(2),缓存f(3)、f(2)的结果,不用重复计算。
前后端场景:前端用在性能优化(缓存已加载的路由组件)、表单验证(拆分复杂规则,缓存验证结果)、游戏开发(路径规划);后端用在最优路径问题(物流配送路径规划)、资源分配(服务器资源分配)、库存调度(最优库存分配)。
老炮踩坑提醒:新手最容易陷入“找不到状态转移方程”的困境,其实不用死记硬背,核心是“找到小问题和大问题的关系”,比如斐波那契数列,状态转移方程就是f(n)=f(n-1)+f(n-2),先找简单的情况,再推导复杂情况。
19. 贪心算法(Greedy Algorithm)
人话解读:核心是“每次都选当前最优的选择”,不考虑长远,只看眼前,就像买东西,每次都选最便宜的,不考虑整体性价比,适合简单的最优解场景。
前后端场景:前端用在简单的资源分配(比如页面加载时,优先加载最重要的资源)、表单提交(优先提交必填项);后端用在任务调度(优先执行优先级最高的任务)、资源分配(优先分配资源给最需要的服务)。
老炮踩坑提醒:贪心算法不是万能的,只能解决“局部最优能得到全局最优”的场景,比如找零问题(用最少的硬币找零);如果局部最优不能得到全局最优(比如旅行商问题),就不能用贪心算法,改用动态规划。
20. 回溯算法(Backtracking)
人话解读:核心是“尝试+回退”,就像走迷宫,走一条路,如果走不通,就退回来,换另一条路,直到找到出口。适合解决“组合、排列、选择”类问题,比如找出所有可能的组合。
前后端场景:前端用在表单组合(比如生成所有可能的表单选项组合)、树形结构筛选(比如找出所有符合条件的子节点组合);后端用在组合查询(比如找出所有符合条件的用户组合)、权限分配(生成所有可能的权限组合)。
老炮踩坑提醒:回溯算法的效率较低,数据量较大时,会严重卡顿,建议搭配剪枝操作(比如提前判断某条路径走不通,直接跳过,不继续尝试),提升效率。
21. 深度优先搜索(DFS)
人话解读:核心是“一条路走到黑,走不通再回退”,就像探险,先深入一个洞穴,直到走到尽头,再退回来,去另一个洞穴,适合遍历树形、图结构。
前后端场景:前端用在树形结构遍历(比如多级菜单渲染、树形组件查找)、图结构遍历(比如前端可视化图的节点遍历);后端用在目录遍历(比如遍历服务器所有文件目录)、图结构查询(比如社交网络中的好友关系遍历)。
老炮踩坑提醒:DFS容易出现栈溢出(尤其是深度很深的结构),可以用迭代替代递归,或者限制遍历深度;另外,遍历的时候要标记已访问的节点,避免重复遍历。
22. 广度优先搜索(BFS)
人话解读:和DFS相反,核心是“逐层遍历”,就像洪水泛滥,从中心向外扩散,先遍历完当前层的所有节点,再遍历下一层,适合找最短路径、层级遍历。
前后端场景:前端用在树形结构层级遍历(比如树形组件的层级展开)、最短路径查找(比如前端小游戏的最短路径);后端用在图结构最短路径(比如物流最短路径)、层级查询(比如查询某个分类下的所有层级子分类)。
老炮踩坑提醒:BFS需要用队列存储待遍历的节点,数据量较大时,会占用较多内存;如果只需要遍历深度较浅的结构,用BFS更高效;深度较深,用DFS更省内存。
23. 拓扑排序(Topological Sort)
人话解读:适合“有依赖关系”的排序,核心是“先完成依赖项,再完成被依赖项”,就像盖房子,先打地基,再砌墙,最后封顶,不能颠倒顺序。
前后端场景:前端用在任务调度(比如页面加载时,先加载依赖的资源,再加载页面内容)、组件渲染(先渲染父组件,再渲染子组件);后端用在任务调度(比如先执行依赖的任务,再执行主任务)、数据库迁移(先迁移依赖的表,再迁移其他表)。
老炮踩坑提醒:拓扑排序只适合“无环图”,如果有环(比如A依赖B,B依赖A),就无法进行拓扑排序;先判断图是否有环,再进行拓扑排序。
24. 二分查找变种(Binary Search Variants)
人话解读:在基础二分查找的基础上,优化适配不同场景,比如找第一个大于目标值的元素、找最后一个小于目标值的元素,核心还是“折半查找”,只是调整了判断条件。
前后端场景:前端用在有序列表精准筛选(比如找第一个价格大于100的商品)、下拉框定位(找第一个符合关键词的选项);后端用在数据库精准查询(比如找第一个注册时间大于2023年的用户)、海量有序数据筛选。
老炮踩坑提醒:新手容易混淆不同变种的判断条件,比如找“第一个大于目标值”和“最后一个小于目标值”,判断条件差异很大,建议先明确需求,再写判断条件,避免出错。
25. 快速选择(Quick Select)
人话解读:基于快速排序的思想,核心是“找到数组中第k大(或第k小)的元素”,不用排序整个数组,只需要找到目标元素,效率比排序后再查找高很多。
前后端场景:前端用在列表筛选(比如找出商品列表中价格第3高的商品)、排行榜(比如找出用户积分前10名);后端用在海量数据统计(比如找出订单金额第100大的订单)、排行榜统计。
老炮踩坑提醒:快速选择的最坏时间复杂度是O(n²),和快速排序一样,通过随机选择基准值,能避免极端情况,提升效率;如果对效率要求极高,可搭配其他算法优化。
26. 并查集(Union-Find)
人话解读:核心是“合并集合、查找元素所属集合”,就像给一群人分组,把有关系的人分到同一个组,然后快速判断两个人是否在同一个组,适合处理“连通性”问题。
前后端场景:前端用在图结构连通性判断(比如前端可视化图的节点连通性)、组件关联判断(比如判断两个组件是否有关联);后端用在网络连通性判断(比如判断两个服务器是否连通)、数据分组(比如将关联的用户分到同一个组)。
老炮踩坑提醒:并查集需要注意“路径压缩”和“按秩合并”,否则效率会很低;路径压缩能减少查找次数,按秩合并能减少合并后的树的深度,两者结合,能显著提升效率。
27. 堆排序(Heap Sort)
人话解读:基于堆(大根堆、小根堆)的排序算法,核心是“先构建堆,再依次取出堆顶元素,重新调整堆”,就像堆金字塔,先把最大的石头放在最上面,然后依次取出最大的石头,再调整金字塔,效率稳定。
前后端场景:前端用在排行榜(比如用户积分排行榜,取前10名)、优先队列(比如优先处理重要的任务);后端用在海量数据排序(比如100万条数据排序,效率稳定)、优先队列(比如消息队列的优先级排序)。
老炮踩坑提醒:堆排序的时间复杂度是O(n log n),效率稳定,适合数据量较大的场景;但实现起来比快速排序复杂,日常开发中,如果不需要稳定排序,优先用快速排序,需要稳定排序,可用堆排序。
28. 基数排序变种(Radix Sort Variants)
人话解读:在基础基数排序的基础上,适配不同数据类型,比如字符串基数排序(按字符ASCII码排序)、负数基数排序(处理负数的位数排序),核心还是“按位数/字符排序”。
前后端场景:前端用在字符串排序(比如用户名按字母排序)、负数排序(比如用户余额排序,包含负数);后端用在字符串数据排序(比如商品名称排序)、负数数据统计(比如用户盈亏排序)。
老炮踩坑提醒:字符串基数排序需要注意字符的长度,长度不一致时,需要补位(比如补空格);负数基数排序需要处理符号位,先按绝对值排序,再调整符号。
29. 桶排序变种(Bucket Sort Variants)
人话解读:优化基础桶排序的不足,比如动态桶大小(根据数据分布调整桶的大小)、多维度桶排序(按多个维度分桶),核心还是“分桶+排序”,适配更多场景。
前后端场景:前端用在多维度筛选(比如商品按价格+销量分桶排序)、数据分布不均匀的场景(比如大部分数据在一个区间,动态调整桶大小);后端用在多维度数据排序(比如用户按年龄+消费金额分桶排序)、海量数据不均匀分布场景。
老炮踩坑提醒:动态桶大小的关键是“统计数据分布”,先统计数据的最大值、最小值,再根据分布调整桶的大小和数量,避免出现“一个桶装大部分数据”的情况。
30. 计数排序变种(Counting Sort Variants)
人话解读:优化基础计数排序的不足,比如处理负数(调整计数数组的偏移量)、处理非整数(将非整数转换为整数再排序),核心还是“统计次数+输出”。
前后端场景:前端用在负数排序(比如用户积分排序,包含负数)、非整数排序(比如商品评分排序,1-5分,包含小数);后端用在负数数据统计(比如用户盈亏排序)、非整数数据排序(比如订单金额排序,包含小数)。
老炮踩坑提醒:处理非整数时,需要先将非整数乘以一个倍数,转换为整数,排序后再除以倍数,避免精度丢失;处理负数时,需要计算偏移量,将负数映射到正数区间,排序后再调整回负数。
31. 字符串匹配(String Matching)
人话解读:核心是“在一个字符串中,找到另一个子字符串的位置”,就像在一篇文章中,找到某个关键词的位置,常用的有BF算法、KMP算法、BM算法。
前后端场景:前端用在搜索功能(比如页面搜索关键词)、表单验证(比如验证手机号、邮箱格式);后端用在日志分析(比如查找日志中的关键词)、接口参数校验(比如验证字符串格式)。
老炮踩坑提醒:BF算法简单但效率低,适合短字符串匹配;KMP算法效率高,适合长字符串匹配,但实现复杂;BM算法效率比KMP还高,是实际开发中常用的字符串匹配算法,建议重点掌握。
32. KMP算法(Knuth-Morris-Pratt Algorithm)
人话解读:字符串匹配的“高效算法”,核心是“利用子字符串的前缀和后缀,避免重复比较”,就像找关键词时,发现前面一部分已经匹配上了,后面就不用重新比较,直接跳过,提升效率。
前后端场景:前端用在长字符串匹配(比如页面长文本搜索关键词)、复杂表单验证(比如验证复杂的密码格式);后端用在日志分析(比如查找长日志中的关键词)、大文本匹配(比如匹配长文本中的特定片段)。
老炮踩坑提醒:KMP算法的核心是“前缀函数”,新手容易搞懂前缀函数的逻辑,建议先理解前缀和后缀的概念,再推导前缀函数,不用死记硬背代码,理解原理后就能轻松实现。
33. BM算法(Boyer-Moore Algorithm)
人话解读:比KMP算法效率更高的字符串匹配算法,核心是“从后往前匹配,利用坏字符规则和好后缀规则,快速跳过不匹配的部分”,就像找关键词时,从关键词的最后一个字符开始匹配,不匹配就直接跳过,效率极高。
前后端场景:前端用在大量文本搜索(比如富文本编辑器的关键词搜索)、长字符串匹配;后端用在日志分析(比如海量日志中的关键词匹配)、大文本处理(比如处理几GB的文本,查找特定片段)。
老炮踩坑提醒:BM算法的坏字符规则和好后缀规则,新手容易混淆,建议先掌握坏字符规则(简单易懂),再学习好后缀规则;实际开发中,大部分场景用坏字符规则就足够,能满足效率需求。
34. BF算法(Brute Force String Matching)
人话解读:字符串匹配的“基础算法”,核心是“逐个字符对比”,从主字符串的第一个字符开始,和子字符串的第一个字符对比,不匹配就往后移一位,直到匹配成功或结束,简单易实现,但效率低。
前后端场景:前端用在短字符串匹配(比如验证验证码、短文本搜索);后端用在短字符串匹配(比如验证接口参数中的短字符串)。
老炮踩坑提醒:BF算法只适合短字符串匹配,长字符串匹配绝对不用,否则效率会极低;比如匹配1000个字符的主字符串和100个字符的子字符串,BF算法最多需要901次对比,而KMP、BM算法只需要几十次。
35. 编辑距离(Edit Distance)
人话解读:核心是“计算两个字符串之间的相似度”,通过插入、删除、替换字符,将一个字符串转换成另一个字符串,所需的最少操作次数,操作次数越少,相似度越高。就像修改文章,修改的次数越少,和原文越像。
前后端场景:前端用在搜索推荐(比如用户输入关键词有误,推荐相似的关键词)、文本对比(比如富文本编辑器的文本对比);后端用在日志对比(比如对比两次日志的差异)、数据去重(比如判断两个字符串是否相似,避免重复)。
老炮踩坑提醒:编辑距离的计算可以用动态规划实现,新手容易忽略边界条件(比如一个字符串为空,另一个字符串的长度就是编辑距离);另外,编辑距离的阈值可以调整,根据需求判断两个字符串是否相似。
36. 最长公共子序列(LCS)
人话解读:核心是“找到两个字符串中,最长的、不连续但顺序一致的子序列”,就像两篇文章,找到最长的相似片段,不要求连续,但顺序要一致。
前后端场景:前端用在文本对比(比如对比两个文本的相似片段)、搜索推荐(比如根据用户输入的关键词,推荐有最长公共子序列的内容);后端用在日志分析(比如对比两次日志的相似部分)、数据相似度判断。
老炮踩坑提醒:LCS的核心是动态规划,新手容易搞混“子序列”和“子串”(子串是连续的,子序列是不连续的);另外,LCS的计算效率较低,数据量较大时,需要优化动态规划的空间复杂度。
37. 最长公共子串(Longest Common Substring)
人话解读:和LCS类似,但要求子串必须连续,核心是“找到两个字符串中,最长的、连续且顺序一致的子串”,就像两篇文章,找到最长的连续相似片段。
前后端场景:前端用在文本对比(比如对比两个文本的连续相似片段)、关键词匹配(比如找到两个文本中最长的相同关键词);后端用在日志分析(比如找到两次日志中连续的相同片段)、数据去重(比如判断两个字符串是否有长连续相同片段)。
老炮踩坑提醒:最长公共子串的实现可以用动态规划,也可以用滑动窗口,滑动窗口的效率更高,适合长字符串;新手容易和LCS搞混,记住:子串连续,子序列不连续。
38. 最长递增子序列(LIS)
人话解读:核心是“找到数组中,最长的、严格递增的子序列”,不要求连续,但顺序要一致,就像找一串数字中,最长的上升趋势片段。比如数组[3,1,2,4,5],最长递增子序列是[1,2,4,5],长度为4,虽然3在最前面,但不影响后续的递增趋势。
前后端场景:前端用在数据可视化(比如展示用户成长值的上升趋势,提取最长递增片段)、列表排序优化(比如筛选出符合递增规律的商品序列);后端用在数据分析(比如分析用户消费金额的递增趋势)、股票价格分析(提取最长上涨周期)。
老炮踩坑提醒:新手容易用暴力枚举(遍历所有子序列),效率极低,数据量超过20条就会卡顿;推荐用动态规划或贪心+二分查找实现,时间复杂度可优化到O(n log n),适合海量数据处理。
39. 最长递减子序列(LDS)
人话解读:和LIS相反,核心是“找到数组中,最长的、严格递减的子序列”,不要求连续,顺序一致即可,就像找一串数字中,最长的下降趋势片段。比如数组[5,4,2,3,1],最长递减子序列是[5,4,2,1],长度为4。
前后端场景:前端用在数据筛选(比如筛选商品价格的下降趋势序列)、可视化图表(展示数据的下降规律);后端用在数据分析(比如分析用户活跃度的下降趋势)、库存预警(提取库存数量的递减片段,及时补货)。
老炮踩坑提醒:无需单独写算法,可将数组反转后,求反转数组的LIS,结果就是原数组的LDS,节省开发成本;注意区分“严格递减”和“非递增”,严格递减要求每个元素都比前一个小,非递增允许相等。
40. 最短路径算法(Dijkstra Algorithm)
人话解读:图结构中的“导航神器”,核心是“从起点出发,逐步找到到其他所有节点的最短路径”,就像手机导航,输入起点和终点,导航会计算出距离最短的路线,优先选择近路,不绕远。
前后端场景:前端用在地图类应用(比如前端小游戏的地图导航、本地地图的最短路径计算)、可视化图(比如节点之间的最短连接);后端用在物流配送(计算配送员到多个站点的最短路径)、网络路由(计算数据传输的最短路径)。
老炮踩坑提醒:Dijkstra算法不适合有负权边的图(比如边的权重为负数),遇到负权边,会计算出错;此时改用Bellman-Ford算法,虽然效率低,但能处理负权边场景。
41. Bellman-Ford算法
人话解读:最短路径算法的“补充版”,核心是“能处理有负权边的图,通过多次松弛操作,找到起点到其他所有节点的最短路径”,就像导航时,虽然有一段路是逆行(负权),但依然能计算出整体最短路径,适合复杂场景。
前后端场景:前端用在复杂可视化图(比如包含负权边的节点连接)、小游戏(比如带有惩罚机制的路径规划);后端用在网络路由(处理数据传输中的负权损耗)、金融数据分析(处理带有负收益的路径计算)。
老炮踩坑提醒:Bellman-Ford算法的时间复杂度是O(nm)(n是节点数,m是边数),效率比Dijkstra算法低,数据量较大时,优先用Dijkstra算法;只有存在负权边时,才用Bellman-Ford算法。
42. Floyd-Warshall算法
人话解读:最短路径算法的“全能版”,核心是“计算图中所有节点之间的最短路径”,不用指定起点,一次性求出任意两个节点之间的最短距离,就像一张完整的地图,标注出所有地点之间的最短路线,适合全局规划。
前后端场景:前端用在全局可视化图(比如展示所有节点之间的最短连接)、多起点多终点的路径规划;后端用在物流调度(计算多个仓库到多个站点的最短路径)、网络规划(计算所有服务器之间的最短传输路径)。
老炮踩坑提醒:Floyd-Warshall算法的时间复杂度是O(n³),效率较低,节点数超过100时,会严重卡顿;适合节点数少、需要全局路径的场景,节点数多的场景,优先用Dijkstra算法循环计算。
43. 矩阵快速幂(Matrix Exponentiation)
人话解读:核心是“快速计算矩阵的n次幂”,通过拆分幂次,减少计算次数,就像计算2^10,不用2×2×…×2(10次),而是拆成(2^5)²,再拆成((2²)×2)²,大大减少计算量,适合大规模矩阵计算。
前后端场景:前端用在数据可视化(比如矩阵变换、图形旋转缩放)、机器学习(简单的矩阵运算优化);后端用在算法优化(比如斐波那契数列的快速计算)、大数据分析(大规模矩阵运算)、人工智能(神经网络中的矩阵计算)。
老炮踩坑提醒:新手容易忽略矩阵乘法的规则,导致计算出错;记住:矩阵A×矩阵B,要求A的列数等于B的行数,否则无法相乘;另外,矩阵快速幂的核心是“二分拆分”,拆分成2的幂次,提升计算效率。
44. 前缀和(Prefix Sum)
人话解读:核心是“提前计算数组的前缀和,快速求解任意子数组的和”,就像提前算好从家到每个站点的距离,要算两个站点之间的距离,直接用后面站点的距离减去前面站点的距离,不用重新计算,效率极高。
前后端场景:前端用在数据统计(比如统计页面中某段时间的用户访问量)、列表筛选(比如筛选某段索引范围内的数值和);后端用在海量数据统计(比如统计某段时间内的订单总金额)、日志分析(统计某段时间内的错误日志数量)。
老炮踩坑提醒:前缀和适合“多次查询子数组和”的场景,如果只查询一次,直接遍历计算更高效;另外,注意前缀和数组的初始化,通常前缀和数组的长度比原数组长1,方便计算边界情况。
45. 差分(Difference)
人话解读:前缀和的“逆运算”,核心是“通过差分数组,快速对数组的某一段区间进行加减操作”,就像给一排树木浇水,不用一棵一棵浇,而是给一段区间的树木统一浇水,再通过差分数组快速更新每棵树的浇水量。
前后端场景:前端用在批量更新(比如批量调整列表中某段索引的数值)、数据可视化(比如批量调整图表中某段区间的数值);后端用在批量操作(比如批量更新某段时间内的用户积分)、海量数据批量修改。
老炮踩坑提醒:差分数组的核心是“区间更新、单点查询”,如果需要单点更新、区间查询,优先用前缀和;另外,差分数组更新后,需要通过前缀和还原原数组,避免直接使用差分数组作为结果。
46. 位运算(Bit Manipulation)
人话解读:核心是“直接操作二进制位”,比如与、或、异或、左移、右移,就像操作积木的最小单元,通过组合这些操作,实现高效的计算,比普通的加减乘除效率高很多,适合底层开发、性能优化。
前后端场景:前端用在性能优化(比如判断奇偶性、交换两个变量的值,不用临时变量)、权限控制(用二进制位表示不同的权限,通过位运算判断权限);后端用在底层开发(比如服务器内存管理)、海量数据去重(用位运算压缩数据)、加密算法(基础位运算组合)。
老炮踩坑提醒:新手容易混淆位运算的优先级,比如与、或、异或的优先级低于加减乘除,建议用括号明确优先级;另外,右移操作要注意符号位,正数右移补0,负数右移补1,避免出现意想不到的结果。
47. 异或运算(XOR)
人话解读:位运算中的“神器”,核心是“两个二进制位相同则为0,不同则为1”,就像对比两个数字的二进制,找不同的地方,还有两个实用特性:任何数异或0等于自身,任何数异或自身等于0,适合很多场景的优化。
前后端场景:前端用在数据去重(比如数组中只出现一次的数字)、变量交换(不用临时变量,a = a^b, b = a^b, a = a^b);后端用在数据加密(简单的异或加密)、校验数据(判断两个数据是否一致)、海量数据去重。
老炮踩坑提醒:异或运算适合“成对出现的数据”场景,比如数组中除了一个数字,其他都成对出现,用异或能快速找到这个数字;另外,异或运算不适合复杂加密,只能用于简单的校验和去重。
48. 位掩码(Bit Mask)
人话解读:基于位运算的“权限管理神器”,核心是“用一个整数的二进制位,代表不同的状态或权限”,比如用一个8位整数,每一位代表一个权限,1表示拥有该权限,0表示没有,通过位运算快速判断、修改权限。
前后端场景:前端用在权限控制(比如页面按钮的权限,每一位代表一个按钮的权限)、状态管理(比如组件的多种状态,用二进制位表示);后端用在用户权限管理(比如用户的操作权限,用位掩码存储,节省数据库空间)、状态标记(比如订单的多种状态,用位掩码表示)。
老炮踩坑提醒:位掩码适合权限/状态数量较少的场景(比如不超过32种,对应32位整数),如果权限/状态数量过多,建议用其他方式存储;另外,修改权限时,注意用位运算(与、或、异或),避免直接修改整数,导致权限混乱。
49. 质数筛选(Sieve of Eratosthenes)
人话解读:核心是“快速筛选出小于等于n的所有质数”,就像筛子一样,先把2的倍数筛掉,再把3的倍数筛掉,依次类推,剩下的就是质数,效率比逐个判断质数高很多,适合大规模质数筛选。
前后端场景:前端用在数学类应用(比如质数计算、数学游戏);后端用在加密算法(比如RSA加密,需要大量质数)、数学计算(比如大数据中的质数统计)、密码学(基础质数生成)。
老炮踩坑提醒:新手容易忽略筛法的优化,比如只需要筛到√n即可,因为大于√n的合数,其因子一定小于√n,已经被筛掉;另外,筛选时可以用布尔数组存储状态,节省内存空间。
50. 最大公约数(GCD)
人话解读:核心是“找到两个数的最大公约数,即能同时整除这两个数的最大整数”,就像找两个数的“共同因数”中最大的那个,比如12和18的最大公约数是6,常用欧几里得算法(辗转相除法)计算。
前后端场景:前端用在数学计算(比如分数化简、比例计算)、数据可视化(比如图形缩放比例);后端用在数学运算(比如分数运算、比例调整)、加密算法(比如RSA加密中的公约数计算)、大数据比例统计。
老炮踩坑提醒:欧几里得算法的核心是“gcd(a,b) = gcd(b,a mod b)”,直到b为0,此时a就是最大公约数;新手容易混淆最大公约数和最小公倍数,记住:最小公倍数 = 两个数的乘积 ÷ 最大公约数。
51. 最小公倍数(LCM)
人话解读:核心是“找到两个数的最小公倍数,即能同时被这两个数整除的最小整数”,就像找两个数的“共同倍数”中最小的那个,比如12和18的最小公倍数是36,通常通过最大公约数计算,不用单独枚举。
前后端场景:前端用在时间计算(比如两个周期的重合时间)、数学计算(比如分数通分);后端用在任务调度(比如两个任务的重合执行时间)、时间统计(比如多个周期的共同时间节点)。
老炮踩坑提醒:计算最小公倍数时,先计算最大公约数,再用“两个数的乘积 ÷ 最大公约数”,避免直接枚举倍数,效率极低;另外,注意两个数的乘积可能会溢出,尤其是大数,需要做溢出处理。
52. 随机算法(Random Algorithm)
人话解读:核心是“生成随机数或随机序列”,就像掷骰子,每次出现的结果都是随机的,没有固定规律,适合需要随机化的场景,比如抽奖、随机推荐,常用伪随机数生成(计算机无法生成真正的随机数,只能生成伪随机数)。
前后端场景:前端用在抽奖功能(比如大转盘、随机抽奖)、随机推荐(比如随机推荐商品、文章)、小游戏(比如随机生成敌人位置);后端用在随机采样(比如从海量数据中随机抽取样本)、密码生成(随机生成密码、Token)。
老炮踩坑提醒:伪随机数是基于种子生成的,如果种子相同,生成的随机序列也相同,适合需要可复现的场景;如果需要更接近真实随机的结果,可结合系统时间、硬件信息作为种子;另外,抽奖场景要注意避免随机数被篡改,确保公平性。