自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(124)
  • 收藏
  • 关注

原创 算法【乘法快速幂、矩阵快速幂】

乘法快速幂用于求一个数的高次方,矩阵快速幂用于求一个方阵的高次方。固定关系的1维k阶递推表达式,用矩阵快速幂求解时间复杂度O(logn * k的3次方)固定关系的k维1阶递推表达式,用矩阵快速幂求解时间复杂度O(logn * k的3次方)下面通过题目加深理解。题目一分析:对于次方进行二进制判断,如果当前位是1,则结果乘上当前算子,否则结果不变,每次判断后次方右移一位直到为0,算子最开始是底数,每次循环后,算子更新为自身的平方。代码如下。

2025-02-21 14:51:18 966

原创 算法【质数判断、质因子分解、质数筛】

本文讲解判断值较小的数字是否为质数、判断值较大的数字是否为质数,了解Miller-Rabin测试的大概过程 + 会用模版即可、某个数字所有质数因子的分解,掌握最常用的方法足够了、找出1~n范围内所有的质数,埃氏筛、欧拉筛,其实掌握埃氏筛足够。判断n是否是质数,Miller-Rabin测试大概过程:1.每次选择1 ~ n-1范围上的随机数字,或者指定一个比n小的质数,进行测试2.测试过程的数学原理不用纠结,不重要,因为该原理除了判断质数以外,不再用于别的方面。

2025-02-21 14:51:10 511

原创 算法【博弈类问题】

本文最开始讲解一些常见博弈类问题如巴什博弈(Bash)、尼姆博弈(Nim)、斐波那契博弈(Fibonacci)、威佐夫博弈(Wythoff)。通过这些讲解会发现,这些博弈问题在考场上要临时想清楚是不太可能的,所以需要后面的内容即SG函数、SG定理的内容,大多数博弈类问题都可以根据SG定理来解决。博弈类问题大致分为,公平组合游戏、非公平组合游戏(绝大多数的棋类游戏)、反常游戏。只需要关注公平组合游戏(ICG),反常游戏是公平组合游戏的变形,经济类博弈也不是课程所讨论的范围。

2025-02-21 14:50:46 817

原创 算法【贪心经典题目专题6】

然后先将前k-1名工人放入大根堆维护他们的工作质量,从第k名工人开始遍历,因为已经有序,所以这第k名工人和堆里的工人进行工资计算时,是用遍历到的工人的最小期望除以工作质量乘总质量。更新答案之后,将遍历到的工人的工作质量和堆顶的工作质量进行比较,如果比堆顶的工作质量小,则将堆顶的工作质量弹出,遍历到的工作质量入堆。然后将这两种可能性产生的集合的最后一个下标和累加和入堆,将答案数组填满即可。分析:首先进行词频统计,然后对前导零进行判断,如果1到9的词频都小于等于1,则取0到9中最大的词频不为0的数返回。

2025-02-19 09:29:44 367

原创 算法【贪心经典题目专题5】

如果当前水龙头数可以覆盖的最右下标等于遍历到的下标则需要判断,如果多用一个水龙头可以覆盖的最右下标依旧等于当前下标,则代表即使多用一个水龙头,也不能覆盖住后一个范围,所以返回-1;否则多用一个水龙头,当前最右下标更新为多用一个水龙头的最右下标。分析:这道题用cur代表走完当前步数可以来到的最大长度,next代表如果多走一步可以来到的最大长度,然后遍历索引,如果当前步数可以来到的最大长度小于遍历到的索引,步数加1,最大长度更新为多走一步可以来到的最大长度,每一次遍历索引都会更新多走一步可以来到的最大长度。

2025-02-19 09:11:25 277

原创 算法【贪心经典题目专题4】

分析:注意到操作并不会改变数字的奇偶性,所以可以将nums数组和target数组中的奇数和偶数分组,并且nums数组中的奇数个数等于target数组中的奇数个数,nums数组中的偶数个数等于target数组中的偶数个数,并且对这四个数组进行从小到大排序。如果当前员工阅读值较小,则加上之前员工中最大的阅读值,更新答案,最后返回时,答案除以2。分析:用一个大根堆维护可以加油的加油站,当当前无法到达终点时,加油量最大的那个加油站,如果还是无法到达终点更新可以加油的加油站,加油量最大的加油站,循环往复。

2025-02-17 21:28:04 491

原创 算法【贪心经典题目专题3】

Ki代表折扣系数,Bi代表票价,举个例子 : Ki = 2, Bi = 10,如果只有1个人买票,单张门票的价格为 : Bi - Ki * 1 = 8,所以这1个人游玩该项目要花8元,如果有2个人买票,单张门票的价格为 : Bi - Ki * 2 = 6,所以这2个人游玩该项目要花6 * 2 = 12元,如果有5个人买票,单张门票的价格为 : Bi - Ki * 5 = 0,所以这5个人游玩该项目要花5 * 0 = 0元,如果有更多人买票,都认为花0元。来自真实大厂笔试,没有在线测试。

2025-02-17 21:27:54 985

原创 算法【贪心经典题目专题2】

遍历每一次选择项目的机会,对于当前资本可以解锁的项目的纯利润进入大根堆,选择当前纯利润最大的项目进行投资,将纯利润加入当前资本进行下一次的选择。分析:首先按照开始时间进行排序,然后用一个小根堆维护结束时间,遍历会议的时候,对于当前时间可以解锁的会议的结束时间进入小根堆,选择可以解锁的会议中结束时间最小的会议进行参加。分析:以会议的结束时间从小到大进行排序,对于当前时间如果小于等于当前会议的开始时间则代表可以参加,时间更新为当前会议的结束时间,遍历所有会议即可得到答案。来自真实大厂笔试,没有在线测试。

2025-02-16 20:14:21 830

原创 算法【贪心经典题目专题1】

对于遍历到的线段,先清除小根堆中线段的终点小于等于当前线段起点的终点,然后将当前线段的终点加入小根堆,现在小跟堆中终点的个数就是以当前线段起点为左边界的线段重合最大数,遍历所有线段即可得到答案。如果当前时间加上持续时间大于结束时间,则需要对已经修读的课程中持续时间最大的课程进行比较,如果当前课程的持续时间小于已经修读的课程中最大的持续时间则修读当前课程,不修读最大持续时间的课程。广义的贪心指通过分析题目自身的特点和性质,只要发现让求解答案的过程得到加速的结论,都算广义的贪心。下面通过题目加深理解。

2025-02-16 19:55:21 582

原创 算法【动态规划中根据数据量猜解法的技巧】

对于一个具体的题目,方法运行的指令条数不能超过10^7 ~ 10^8规模,否则就会超时那么就可以利用这个条件:1.想出能通过的方法再去实现2.确定优化做到什么程度才能通过下面通过题目加深理解。

2025-02-15 16:10:34 927

原创 算法【动态规划中得到具体决策方案的技巧】

很多动态规划题目要求返回的答案不是一个简单数值,而是一个具体的方案1.利用动态规划表生成决策路径,如题目一、题目二、题目三2.有时候需要增加额外的路径收集结构,如题目四对这一类的题目来说,动态规划是最重要的,得到具体方案只是一个比较简单的处理技巧。下面通过题目来加深理解。

2025-02-15 16:10:24 424

原创 算法【动态规划中使用观察优化枚举】

动态规划的问题中,已经写出了记忆化搜索的版本,还要写出严格位置依赖的版本,意义在于不仅可以进行空间压缩优化;关键还在于,很多时候通过进一步观察,可以优化枚举,让时间复杂度更好。优化枚举的技巧很多,本文讲解根据观察优化。动态规划方法的复杂度大致可以理解为:O(状态数量 * 每个状态的枚举代价)。当每个状态的枚举代价为O(1),那么写出记忆化搜索的版本,就是时间复杂度最好的实现了。但是当每个状态的枚举代价比较高的时候,记忆化搜索的版本可能不是最优解,可能存在进一步的优化。

2025-02-15 16:10:11 834

原创 算法【数位dp】

数位dp的尝试方式并不特殊,绝大多数都是线性展开,类似从左往右的尝试。之前的文章已经讲过大量在数组上进行线性展开的题目,数位dp是在数字的每一位上进行线性展开而已。不同的题目有不同的限制,解题核心在于:可能性的整理、排列组合的相关知识。解决数位dp的问题推荐使用记忆化搜索的方式,可能性的展开会很好写,不必刻意追求进一步改写,递归写出来问题就解决了,位数多就挂缓存,位数不多甚至不挂缓存也能通过。下面通过题目加深理解。

2025-02-11 20:56:06 839

原创 算法【状压dp】

状压dp是指设计一个整型可变参数status,利用status的位信息,来表示某个样本是否还能使用,然后利用这个信息进行尝试。写出尝试的递归函数 -> 记忆化搜索 -> 严格位置依赖的动态规划 -> 空间压缩等优化。如果有k个样本,那么表示这些样本的状态,数量是2^k。所以可变参数status的范围: 0 ~ (2^k)-1样本每增加一个,状态的数量是指数级增长的,所以状压dp能解决的问题往往样本数据量都不大。

2025-02-11 20:55:47 836

原创 算法【树型dp】

树是指头节点没有父亲,其他节点只有一个父亲的有向无环图,直观理解为发散状。在树上,从头节点出发到任何节点的路径是唯一的,不管二叉树还是多叉树都如此。树型dp在树上做动态规划,依赖关系比一般动态规划简单。因为绝大部分多数都是父依赖子。树型dp套路1)分析父树得到答案需要子树的哪些信息2)把子树信息的全集定义成递归返回值3)通过递归让子树返回全集信息4)整合子树的全集信息得到父树的全集信息并返回dfn序用深度优先遍历的方式遍历整棵树,给每个节点依次标记序号,编号从小到大的顺序就是dfn序。

2025-02-06 15:26:02 679

原创 算法【区间dp】

区间dp是指大范围的问题拆分成若干小范围的问题来求解。可能性展开的常见方式:1)基于两侧端点讨论的可能性展开。2)基于范围上划分点的可能性展开。下面通过题目加深理解。题目一分析:这道题的思路非常简单,判断left到right区间的字符串成为回文串最少插入次数,只需要判断left和right处字符是否相等,相等则插入次数为left+1到right-1区间字符串最少插入次数;不相等,则left到right-1的最少插入次数和left+1到right的最小插入次数取最小值即可得到答案。

2025-02-06 11:46:27 841

原创 算法【混合背包】

分析:这道题可以通过硬币的个数将其转化为01背包,完全背包和多重背包。如果硬币的个数是1个,则是01背包;如果硬币的面值×硬币的个数大于当前需要找零的数额,则是完全背包;对于不同的背包进行不同的可能性展开,最后统计,即可得到答案。其中,求dp数组循环中,i为在下标0~i的物品中取。当然,这道题其实可以直接将其当作一个多重背包,二进制优化后转化为01背包进行求解。混合背包是指多种背包模型的组合与转化。下面通过题目加深理解。

2025-02-01 20:01:34 249

原创 算法【多重背包】

就是将多重背包的件数转化为多个二进制背包的形式,这样可以通过转化出的多个物品不同的取舍方案得到对多重背包取不同件数的体现。比如件数为7,可以从1开始,转化为1,2,4三个背包,对于多重背包7件取多少件,可以通过1,2,4这三个背包取或不取得到。其中,dp数组的含义和记忆化搜索中f方法的含义基本相同,因为严格位置依赖的版本就是根据记忆化搜索写出来的。不过,严格位置依赖的版本依旧过不去。分析:这道题就是典型的多重背包模板,对于多重背包可能性的展开也十分容易想到,对于第i个物品不取或者依次取1个、2个、3个等。

2025-02-01 19:56:07 599

原创 算法【完全背包】

完全背包与01背包的区别仅在于每种商品可以选取无限次。时间复杂度O(物品数量 * 背包容量)下面通过题目加深理解。题目一分析:这是一道完全背包的模板题。对于第i个物品的可能性展开也有两种,第一种是不取第i个物品,即就是从0到i-1个物品里面取剩余重量为j的最大价值;第二种是只取一个第i个物品,即从0到i个物品取剩余重量为j-一个i物品重量的最大值+一个i物品的价值。

2025-01-31 16:42:14 929

原创 算法【分组背包】

分组背包是指多个物品分组,每组只能取1件。每一组的物品都可能性展开就可以了。注意时间复杂度不会升阶,O(物品数量 * 背包容量)。下面通过题目加深理解。

2025-01-31 16:41:55 488

原创 算法【有依赖的背包】

分析:对于这道题,可以参考01背包是对每个物品进行可能性的展开,有依赖的背包是对主件进行可能性的展开,所以可能性就比01背包的展开多。对于有两个附件的主件可能性的展开,就有五种,选主件、不选主件、主件和第一个附件一起选、主件和第二个附件一起选、主件和两个附件一起选。对于输入,代码中采用了几个数组结构存储信息,cost数组存储花费代价,value数组存储收益,king数组存储是否是主件,fans数组存储主件有多少个附件,follows数组存储每个主件拥有的附件。下面通过题目加深理解。

2025-01-27 21:42:21 447

原创 算法【01背包】

01背包是背包问题中最基础最简单的类型,只是对每个物品要和不要两种可能性展开,不存在过多的困难。下面通过几个题目加深理解。题目一分析:这个是01背包模板的题目。dp[i][j]表示,在前i个草药里面选,总共时间为j,可以采到的草药的最大总价值。对可能性的展开就是第i个草药选不选第i个草药有两种可能性,不选和选,比较它们的最大值。代码如下。进行空间压缩后的代码如下。

2025-01-27 21:42:07 604

原创 算法【最长递增子序列问题与扩展】

本文讲解最长递增子序列以及最长不下降子序列的最优解,以及一些扩展题目。本文中讲述的是最优解,时间复杂度是O(n*logn),空间复杂度O(n),好实现、理解难度不大。这个问题也可以用线段树来求解,时间和空间复杂度和本节讲的最优解没有区别。下面通过一些题目来加深理解。

2024-11-21 17:01:21 1089

原创 算法【子数组最大累加和问题与扩展】

子数组最大累加和问题是一个非常经典的问题,也比较简单。但是扩展出的问题很多,在笔试、面试中特别常见,扩展出的问题很多非常有趣,解法也比较巧妙。下面通过一些题目来加深理解。

2024-11-21 17:01:05 1155

原创 算法【从递归入手三维动态规划】

从递归到三维动态规划,包含多维费用背包,严格位置依赖的三维动态规划,三维动态规划的空间压缩注意:多维费用背包问题就是很普通的动态规划。但是后面文章里还会安排背包dp的内容,那时候会把其他几种背包问题做汇总讲述。尝试函数有1个可变参数可以完全决定返回值,进而可以改出1维动态规划表的实现。同理,尝试函数有2个可变参数可以完全决定返回值,那么就可以改出2维动态规划的实现。同理,尝试函数有3个可变参数可以完全决定返回值,那么就可以改出3维动态规划的实现。

2024-11-21 17:00:28 967

原创 算法【更多二维动态规划题目】

本文不再从递归入手,而是直接从动态规划的定义入手,来解决更多二维动态规划问题。其中包含一些比较巧妙的尝试思路。

2024-10-07 22:56:29 564

原创 算法【从递归入手二维动态规划】

尝试函数有1个可变参数可以完全决定返回值,进而可以改出1维动态规划表的实现。同理,尝试函数有2个可变参数可以完全决定返回值,那么就可以改出2维动态规划的实现。一维、二维、三维甚至多维动态规划问题,大体过程都是:1.写出尝试递归。2.记忆化搜索(从顶到底的动态规划)。3.严格位置依赖的动态规划(从底到顶的动态规划)。4.空间、时间的更多优化。动态规划表的大小:每个可变参数的可能性数量相乘。动态规划方法的时间复杂度:动态规划表的大小 * 每个格子的枚举代价。

2024-10-07 22:43:54 854

原创 算法【从递归入手一维动态规划】

动态规划:用空间代替重复计算,包含一整套原理和技巧的总和。后面会有非常多的文章介绍动态规划。有些递归在展开计算时,总是重复调用同一个子问题的解,这种重复调用的递归变成动态规划很有收益。如果每次展开都是不同的解,或者重复调用的现象很少,那么没有改动态规划的必要。任何动态规划问题都一定对应着一个有重复调用行为的递归。所以任何动态规划的题目都一定可以从递归入手,逐渐实现动态规划的方法。尝试策略就是转移方程,完全一回事。推荐从尝试入手,因为代码好写,并且一旦发现尝试错误,重新想别的递归代价轻。

2024-09-26 20:41:27 1068

原创 算法【A星、Floyd、Bellman-Ford、SPFA】

假设从点P出发某条边,去往点S,边权为W。最短路存在的情况下,因为1次松弛操作会使1个点的最短路的边数+1,而从源点出发到任何点的最短路最多走过全部的n个点,所以松弛的轮数必然 <= n - 1,所以Bellman-Ford算法时间复杂度O(M*N)。分析:对于是否存在复环的判断,我们可以想到,使用Bellman-Ford算法,同时,加上SPFA优化。其中,在进行松弛操作时,使用了一个next_distance数组,表示所有的条件判断采用上一轮的状态,而不是实时更新的状态,这样就可以保证轮数对应中转次数。

2024-09-26 19:57:14 899

原创 算法【Dijkstra算法及分层图最短路】

Dijkstra算法:给定一个源点,求解从源点到每个点的最短路径长度。单源最短路径算法。适用范围:有向图、边的权值没有负数。彻底暴力的Dijkstra算法,不讲、时间复杂度太差、无意义。普通堆实现的Dijkstra算法,最普遍、最常用。算法核心过程:节点弹出过就忽略,节点没弹出过,让其它没弹出节点距离变小的记录加入堆。反向索引堆实现的Dijkstra算法,最快速、最极致。普通堆实现的Dijkstra算法,时间复杂度O(m * log m),m为边数。

2024-09-20 22:35:51 1007

原创 算法【双向广搜】

双向广搜常见用途1:小优化。bfs的剪枝策略,分两侧展开分支,哪侧数量少就从哪侧展开。2:用于解决特征很明显的一类问题。特征:全量样本不允许递归完全展开,但是半量样本可以完全展开。过程:把数据分成两部分,每部分各自展开计算结果,然后设计两部分结果的整合逻辑。下面通过几个题目加深理解。

2024-09-20 22:35:39 557

原创 算法【宽度优先遍历及其扩展】

宽度优先遍历基本内容1.bfs的特点是逐层扩散,从源头点到目标点扩散了几层,最短路就是多少。2.bfs可以使用的特征是任意两个节点之间的相互距离相同(无向图)。3.bfs开始时,可以是单个源头、也可以是多个源头。4.bfs频繁使用队列,形式可以是单点弹出或者整层弹出。5.bfs进行时,进入队列的节点需要标记状态,防止同一个节点重复进出队列。6.bfs进行时,可能会包含剪枝策略的设计。7.bfs是一个理解难度很低的算法,难点在于节点如何找到路、路的展开和剪枝设计。

2024-09-10 19:40:29 1082

原创 算法【最小生成树】

最小生成树:在无向带权图中选择择一些边,在保证联通性的情况下,边的总权值最小。最小生成树可能不只一棵,只要保证边的总权值最小,就都是正确的最小生成树。如果无向带权图有n个点,那么最小生成树一定有n-1条边。扩展:最小生成树一定是最小瓶颈树(题目5)Kruskal算法(最常用)1.把所有的边,根据权值从小到大排序,从权值小的边开始考虑。2.如果连接当前的边不会形成环,就选择当前的边。3.如果连接当前的边会形成环,就不要当前的边。4.考察完所有边之后,最小生成树的也就得到了。

2024-09-10 19:07:02 958

原创 算法【拓扑排序及其拓展】

拓扑排序:每个节点的前置节点都在这个节点之前。要求:有向图、没有环拓扑排序的顺序可能不只一种。拓扑排序也可以用来判断有没有环1.在图中找到所有入度为0的点。2.把所有入度为0的点在图中删掉,重点是删掉影响!继续找到入度为0的点并删掉影响。3.直到所有点都被删掉,依次删除的顺序就是正确的拓扑排序结果。4.如果无法把所有的点都删掉,说明有向图里有环。下面我们看一些可以直接使用拓扑排序解决的题目。

2024-09-05 22:17:24 889 1

原创 算法【邻接矩阵、邻接表、链式前向星建图】

head数组,下标为点的编号,一般从1开始,值代表从下标编号的点开始遍历的第一条边的编号,初始化为0,代表还没有边。next数组,下标为边的编号,一般从1开始,值代表遍历完这条边后下一条边的编号,如果为0代表没有了。当我们得到一条边的信息:出度节点i、入度节点j,这里建不带权图,我们会有一个cnt变量记录当前的边的编号,这时,由出度节点得到head[i],将next[cnt]赋值为head[i],然后把head[i]更新为cnt,最后将to[cnt]赋值为j。其中,点的编号和边的编号都是从1开始;

2024-09-05 22:17:12 353

原创 算法【洪水填充】

洪水填充是一种很简单的技巧,设置路径信息进行剪枝和统计,类似感染的过程。路径信息不撤销,来保证每一片的感染过程可以得到区分。看似是暴力递归过程,其实时间复杂度非常好,遍历次数和样本数量的规模一致。下面通过一些题目来加深理解。

2024-09-02 19:25:57 1169

原创 算法【并查集】

并查集的使用是如下的场景1.一开始每个元素都拥有自己的集合,在自己的集合里只有这个元素自己。2.find(i):查找i所在集合的代表元素,代表元素来代表i所在的集合。3.bool isSameSet(a, b):判断a和b在不在一个集合里。4.void union(a, b):a所在集合所有元素 与 b所在集合所有元素合并成一个集合。5.各种操作单次调用的均摊时间复杂度为O(1)。并查集的两个优化1.扁平化(一定要做)2.小挂大(可以不做,原论文中是秩的概念,可以理解为粗略高度或者大小)

2024-09-02 19:25:18 798

原创 算法【单调队列】

注意,本文需要:1.掌握用数组方式实现队列(常数时间比语言自己提供的好)。2.掌握滑动窗口。单调队列最经典的用法是解决如下问题:滑动窗口在滑动时,r++代表右侧数字进窗口,l++代表左侧数字出窗口。这个过程中,想随时得到当前滑动窗口的最大值或者最小值。窗口滑动的过程中,单调队列所有调整的总代价为O(n),单次操作的均摊代价为O(1)。注意:这是单调队列最经典的用法,可以解决很多题目。后面将继续介绍其他的用法。下面通过几个题目加深对经典用法的理解。

2024-08-27 11:10:08 872

原创 算法【单调栈】

单调栈最经典的用法是解决如下问题:每个位置都求:1.当前位置的左侧比当前位置的数字小,且距离最近的位置在哪。2.当前位置的右侧比当前位置的数字小,且距离最近的位置在哪。或者每个位置都求:1.当前位置的左侧比当前位置的数字大,且距离最近的位置在哪。2.当前位置的右侧比当前位置的数字大,且距离最近的位置在哪。用单调栈的方式可以做到:求解过程中,单调栈所有调整的总代价为O(n),单次操作的均摊代价为O(1)。单调栈分为有重复值的情况和无重复值的情况。

2024-08-23 20:20:02 992

原创 算法【二分答案法】

本文需掌握二分搜索。二分答案法1.估计最终答案可能的范围是什么,可以定的粗略,反正二分不了几次。2.分析问题的答案和给定条件之间的单调性,大部分时候只需要用到自然智慧。3.建立一个f函数,当答案固定的情况下,判断给定的条件是否达标。4.在最终答案可能的范围上不断二分搜索,每次用f函数判断,直到二分结束,找到最合适的答案。核心点:分析单调性、建立f函数下面通过几个题目加深理解。

2024-08-13 11:19:58 584

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除