- 博客(200)
- 收藏
- 关注
原创 Tarjan(寻找强连通分量)
1,首先进行DFS,用数组dfn存储节点的遍历顺序:dfn[a] = 1,dfn[b] = 2 ……2,接着从遍历最低层 —— d 来迭代可到的的最小层次(low[n]),例如 d 可以回到 b ,3,如果发现无法迭代,则输出,例如回溯到 b 时,b 无法变为更小的数字,那就输出d c b,而dfn[b] = 2,小于dfn[d],那么就将 low[d] 设置为2,利用dfs产生的树,如果最底层节点能回到高层节点,那么他们就连通。3,如果进入的节点 dfn == low ,那么就证明该输出了。
2024-08-15 17:15:54
162
原创 倍增基本思想
那么兔子所有可能条的位置为:(1 * 2 ^ 0)(1 * 2 ^ 1)(1 * 2 ^ 2)(1 * 2 ^ 3)……因为每次跳过的距离都是(1 * 2 ^ 0)(1 * 2 ^ 1)(1 * 2 ^ 2)(1 * 2 ^ 3)每个值相当于多次跳过最小距离(1),也可以说是最小距离的倍增,所以一定能到达。有一个兔子,x到y的距离未知,从x最快跳到y的策略是什么。兔子只能一步一步的跳,然后判断是否到达 y 点,跳 2 ^ 3 而不是 2 ^ 4。
2024-08-14 19:55:26
205
原创 ST表相关
线段树适用于需要频繁修改数组元素且需要实时查询区间信息的情况。由于其具有较快的查询和更新能力,因此。ST表用二维数组存储数据,st[x][y] = z 表示x到y的最大值为z。:ST表适用于数据确定之后不再更改,但需要大量查询的情况。,一旦数据发生变化,就需要重新进行预处理。
2024-08-13 14:00:50
251
原创 线段树相关
线段树适用于需要频繁修改数组元素且需要实时查询区间信息的情况。由于其具有较快的查询和更新能力,因此。线段树是一种二叉搜索树,每个节点表示为【x,y】 = z(x到y的最大值为z):ST表适用于数据确定之后不再更改,但需要大量查询的情况。根节点【1,6】表示第一个到第六个的最大值为 8。例如将 {1,8,6,4,3,5} 存入线段树为。,一旦数据发生变化,就需要重新进行预处理。ST表不支持动态修改操作。
2024-08-13 13:35:21
149
原创 Trie树(字典树、前缀树)
树的每个节点只有一个char,从根节点到一个叶子节点为一个字符串。trie树经常用于字符串的处理。1,判断是否具有对应字符。3,如果没有则创建新节点。2,如果有则共享节点。
2024-08-13 13:09:27
133
原创 双向BFS
4,循环2,3如果起点队列的头节点在另一个队里进入过了,就停止。1,创建两个队列,一个起点进队,一个终点进队。2,将两个对头的可到达节点分别入队。或是等到有一个队为空。
2024-08-12 18:49:27
346
原创 状压DP(状态压缩)
00100表示 c 有水,11011 表示a,b,d,e 有水。比如一共有a,b,c,d,e五口水井。,例如最多有20口水井,否则极易超时。如果超过则推荐使用双向dfs。通过数的二进制来表示状态。
2024-08-12 16:41:45
192
原创 区间DP相关
在区间DP中,我们通常将原问题分解为更小的子问题,这些子问题对应于原问题中不同长度的子区间。通过解决这些子问题,并逐步合并它们的解,我们可以最终得到原问题的解。状态方程为:dp[i][j] = min(dp[i][k] + dp[k+1][j] + case) case是两堆石子的总和。区间dp主要解决一个区间内的问题,比如一排石子,将他们两两相邻合并在一起,每次合并消耗的能量为两堆石子数量之和,求最小消耗。n堆石子,合成一堆一定需要消耗n-1次,那么就遍历最小的消耗合成即可。比如{1,2,3,4}
2024-08-11 21:16:47
313
原创 三种经典背包DP
dp[x-1][j] + value[j],防止了这种情况的出现。则状态转移方程:dp[i][j] = max(dp[i-1][j],dp[i-1][j-weight[i]] + value[i])dp[2*j] == dp[j] + value[j]由于dp[j]还没有被计算过,为0,也就是说,物品不会重复添加。现在降维,将dp转换为一维,即dp[j] = max(dp[j],dp[j-weight[i]])dp[i-1][j-weight[i]] + value[i]代表装第i个物品。
2024-08-11 16:09:11
445
原创 辗转相除法
gcd(a,b) == gcd(b,a%b),每次b在减小,每次b总是逼近0,所以最后的结果是a。原理为欧几里得算法:两个整数的最大公约数是能够同时整除它们的最大的正整数。根据辗转相除法:a,b的最大公约数 == b和a%b的最大公约数。根据gcd(a,b) * lcm(a,b) == a*b。所以gcd(a,b) == gcd(b,a%b)所以a,b的最大公约数x,能同时整除a,b。先给代码,如果看不懂记住代码即可。只需要快速算出gcd即可的出lcm。而n和0的最大公约数为n。
2024-08-10 20:23:32
212
原创 动态规划入门
将原问题分解成若干个子问题,通过解决子问题并保存结果来避免重复计算,从而提高算法效率。那么就可以创建一个数组让他前两项等于1,之后遍历就可以求出答案。总的来说动态规划就是寻找问题特定的公式;最简单的比如斐波那契数列。
2024-08-10 18:57:16
331
原创 记忆化搜索和剪枝
其中8被计算了两次,如果有一个数组记录其结果,就只需要计算一次就可以了。其中在计算一个超级大数位的斐波那契数时,会重复计算很多次其他的数。记忆化搜索就是将每次处理的结果储存起来,不让其重复计算。记忆化搜索主要用于递归中,是优化递归搜索的重要方法。经过unordered_map优化后显然更迅速。而计算9又需要计算8,7;
2024-08-09 21:09:43
281
原创 DFS(深度优先搜索)
实现比BFS简单,只需要递归该节点每一个可到达的节点即可。其中map<节点,set<节点可到达的节点>> m。也是图的遍历方式之一。
2024-08-09 19:08:40
111
原创 BFS(广度优先搜索)
其中map m。注意:不可重复入队,需要一个容器记录是否入队过。2,将头节点的所有可到达节点入队。4,持续循环2,3直到队列为空。1,创建队列,头节点入队。
2024-08-09 19:00:06
190
原创 博弈论基础和SG函数
SG函数1.游戏有两个人参与,二者轮流做出决策。且这两个人的决策都对自己最有利。2.当有一人无法做出决策时游戏结束,无法做出决策的人输。无论二者如何做出决策,游戏可以在有限步内结束。3.游戏中的同一个状态不可能多次抵达。且游戏不会有平局出现。任意一个游戏者在某一确定状态可以作出的决策集合只与当前的状态有关,而与游戏者无关。总的来说就是两个人做选择,每轮一个人选择一次(固定顺序),最后谁先选择不了就失败必胜态。
2024-08-09 16:26:39
463
原创 博弈论三种基础模型(Bashgame,Wythoffgame,Nimmgame)
设两堆物品数分别为a和b(a < b),计算 k = b - a,然后 s = (double)(k * (sqrt(5.0) + 1) / 2)。:对每堆的数目进行亦或(XOR)操作后,若结果为0,则当前局面为必败态;:有三堆(或以上)各若干个物品(数目为x,y,z),两个人轮流从某一堆取任意多的物品,规定每次至少取一个,多者不限,最后。:有两堆各若干个物品,两个人轮流从任意一堆中取出至少一个或者同时从两堆中取出同样多的物品,规定每次。:只有一堆n个物品,两个人轮流从这堆物品中取物品,规定每次。
2024-08-09 10:41:39
252
原创 Manacher(马拉车算法)
Manacher算法,又叫“马拉车”,它可以在时间复杂度和空间复杂度都是O(n)的情况下,求出一个字符串的最长回文串长度。首先将字符拓展为固定形式例如abc拓展为:abc -> #a#b#c ->@#a#b#c%(4,最后将p里的数字减去1然后除以二((p[i]-1)/2)后就是该位置最大的回文长度了。在a的超大回文中,可以直接将左侧回文的复制到右侧,通过这种方法来优化朴素算法。1,变换字符串:abc -> #a#b#c ->@#a#b#c%(3》如果拓展后的边界大于R,就迭代R和Mid。
2024-08-08 21:34:31
411
原创 字符串哈希
在自然溢出法中将字符 * 一个质数后 mod 一个超级大的质数(防止溢出)哈希值为pair的一个键值对。主要用到哈系思想,将不同字符串与对应数字组成key-value的形式。unsigned long long 范围是 0 —— 2^64-1。一般用unsigned long long,因为不需要使用负数。long long 范围是-2^63 —— 2^63-1。常用于判断一个字符串是否出现过,或者出现几次。由两个Base构成,基本不会产生哈希冲突。
2024-08-08 18:59:41
83
原创 一千题,No.0144(不同的循环子字符串)
3 个子字符串分别为 "abcabc","bcabca" 和 "cabcab"。2 个子字符串为 "ee" 和 "leetcodeleetcode"。查看字符串左右的哈希就可以判断出字符串左右是否相等。si到sj的字符串的哈希值为。,请你返回满足下述条件的。和它自身连接形成的。
2024-08-08 18:34:03
101
原创 KMP算法
包括:ε(空串)、"c"、"bc"、"abc"、"babc"和"ababc"包括:ε(空串)、"a"、"ab"、"aba"、"abab"和"ababc"这样在匹配时可以直接向后移,从而减少朴素算法的时间复杂度。最简单的字符串算法,用于寻找字符串是否在文本中出现过。如果前后缀相同那么就意味着。一个较为简单的next函数。字符串"ababc"的。字符串"ababc"的。在kmp中,前后缀应该。效率较高的next函数。
2024-08-08 11:13:01
324
原创 查找所有质因数
这时:数有两种情况(质数,合数),当还是合数时,依然能通过e%i去除质数的乘积值,当是质数时,会走到算法的最后一步。while(num % i == 0) num /= i这一步直接去除了被合数整除的情况,所以不需要判断i是否为质数。所有的合数都可以由一些质数相乘得到,while(num % i == 0) num /= i是为了去除。而得到的所有i都是质数是因为:e%i==0当i是合数的情况是由。1,去除小于2的数字,因为0,1或者负数,因为最小的质数是2。为什么得到的所有i都是质数?
2024-08-07 17:17:28
313
原创 一千题,No.0143(换位与质因数)
如果将 2 和 9 交换得到 m=693457128,其质因数集合为 B = {2, 3, 7, 13, 109, 971}。除了题面中给出的数字外,还可以交换 6 和 1,得到的 123457698 的质因数集合为 {2, 3, 7, 13, 23, 29, 113},交集也是 {2, 3, 7, 13},且这个数字比 693457128 小,故输出。将 n 的任意两位不同数字交换位置后得到数字 m,找到其质因数集合与 n 的质因数集合有最大交集的那个 m。如果这样的 m 不唯一,则输出数值最小者。
2024-08-07 16:49:09
371
原创 一千题,No.0142(有多少零)
有几个10,例如a,b,c相乘的数字,a可以由a1,a2,a3相乘得,则如果a * b构成10,那么(a1,a2,a3)和(b1,b2,b3)中应该有2和5,这么看来,直接循环查找数字中2,5二点数量然后取最小值即可。给定 n 个正整数,请你数数它们的乘积的末尾有多少个零。例如 26、225、48 的乘积是 280800,末尾有 2 个零。输入给出一个不超过 106 的正整数 n,下一行给出 n 个不超过 106 的正整数。在一行中输出给定的 n 个正整数的乘积末尾零的个数。
2024-08-07 15:30:58
181
原创 求图是否存在闭环
(while(y!= father[]y) y = father[y])的父节点设置为x。3,遍历结束后如果每一个x,y的祖先节点都不一样,那么就不存在闭环。2,遍历所有的边,如果x,y节点的祖先节点一样,就证明存在闭环。如果祖先节点不一样,就将y的。
2024-07-29 18:02:38
284
原创 图的最小生成树
2,从最小的边开始遍历,如果左右节点祖先一样,就证明会构成回路,如果不一样,就添加到最小生成树中。2,将里树最近的一条路径添加进去(如果相同则任意一个都行)最小生成树就是找到没有回路的一条路径,而且权值相加最小。3,直到遍历结束,成功的边就是最小生成树了。主要有prim算法和kruskal算法。3,不断重复2直到覆盖到所有节点。prim算法主要运用贪心的思想。1,确定起始点,添加到树里。主要涉及到一个查并集的操作。1,将所有边从小到达排序。
2024-07-29 17:52:56
359
原创 图的最短路径算法
原理也十分简单:从a到b和a到c加上c到b一样,可以通过这一点,将c用所有节点代替,然后每次循环判断整个图,循环中更新,最后将所有自最短路径改为0即可。3,然后遍历图中可到达的节点Point B,判断dis[B]是否大于dis[A] + A到B的距离,然后更新dis。算法主要用到两个数组,一个dis[999]存储最短路径,一个check[999]存储每个节点是否更新。循环2,3,4直到全部check之后,dis中的就是A到达所有节点的最短距离。1,初始化dis,起始点设置为0,其他为无穷大,将起始点入队。
2024-07-28 17:02:56
538
原创 二叉树的遍历
可以看到只有输出位置变化了,其他没有变化。他们一个是进行到底,一个是全面进行。只需要遍历数组即可,所以这里只给出。另外,BFS和DFS也经常用到。广度优先遍历(层次遍历)根的_date的位置。
2024-07-27 19:17:39
138
原创 图的存储结构
邻接矩阵邻接矩阵图的邻接矩阵(Adjacency Matrix) 存储方式是用两个数组来表示图。一个一维数组存储图中顶点信息,一个二维数组(称为邻接矩阵)存储图中的边或弧的信息。用一个二维数组存储两个节点是否连通,再用一个数组存储每个节点的元素的_date下面是实现以下图的代码。
2024-07-27 17:03:52
267
原创 树的存储结构
只有完全二叉树(满二叉树,大小堆)才能使用顺序存储,因为他的存储形式固定。下面是用最易懂的方式实现最简单的二叉树。dad * 2 + 2 = 右孩子。dad * 2 + 1 = 右孩子。dad * 2 +1 = 左孩子。dad * 2 = 左孩子。最常见以一种存储方式。
2024-07-27 16:04:40
215
原创 图的基本概念
在有向图中,顶点的度分为入度(Indegree,指向该顶点的弧的数量)和出度(Outdegree,从该顶点出发的弧的数量)。在有向图中,若存在弧<v, w>,则称v邻接到w,w邻接于v。:若从顶点vi到vj的边有方向,则称为有向边或弧,用有序偶<vi,vj>来表示,vi称为弧尾,vj称为弧头。图一般表示为G(V,E),其中G表示一个图,V是图G中顶点的集合,E是图G中边的集合。:在有向图中,若任意两个顶点都存在双向路径,则称该图为强连通图。:在无向图中,若任意两个顶点都存在路径,则称该图为连通图。
2024-07-27 15:36:05
783
原创 一千题,No.0141(使所有元素都可以被 3 整除的最少操作数)
中所有元素都可以被 3 整除的。一个元素增加或者减少 1。一次操作中,你可以将。
2024-07-26 21:34:48
338
原创 一千题,No.0140(两数之和)
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。因为 nums[0] + nums[1] == 9 ,返回 [0, 1]。整数,并返回它们的数组下标。你可以想出一个时间复杂度小于。你可以按任意顺序返回答案。,请你在该数组中找出。
2024-07-26 18:32:38
117
原创 多叉树的分类
B 树和B+树的主要区别是:B树的节点里包括(next指针,key-value键值对(或者直接用date存储数据)),总之B树的每个节点都存储了数据。4,每个结点中的关键字都按照从小到大的顺序排列,每个关键字的左子树中的所有关键字都小于它,而右子树中的所有关键字都大于它。而在5,11子节点中,左侧是小于5的,中间是大于5但是小于11的,右侧是大于11的。且叶子节点是一种双向链表的形式,B+树的分支节点是用来选择的,省略了date的空间。可以看到B树是有顺序的,即22的左侧为小于22的,右侧为大于22的,
2024-07-26 17:31:32
651
原创 二叉树的分类
完全二叉树二叉树是最常见的树,二叉树的每个节点最多只有两个子节点二叉树的分类完全二叉树指二叉树的所有节点按照从左往右填充是一种完全二叉树,当完全二叉树每个层次都被填满时,就是满二叉树例如上图中的最后一棵树堆堆是一种带有特定排序的完全二叉树,所有节点大于他的所有子节点(大根堆),所有节点小于他的所有子节点(小根堆二叉搜索树二叉搜索树跟大/小根堆相似,堆只要求节点大于(小于)子节而二叉搜索树要求 左节点 > 节点 > 右节点平衡二叉树平衡二叉树是二叉搜索树的一种改进形式。
2024-07-25 18:14:12
1151
原创 栈,队列,链表
从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。
2024-07-25 15:31:13
768
原创 树的基本概念和术语
把它叫做“树”是因为它常看起来像一棵倒挂的树,也就是说它常是根朝上,而叶朝下的。:从根结点开始,根结点的层次为1,根的直接后继层次为2,以此类推。:若一个节点含有子节点,则这个节点称为其子节点的父节点。A的层次为1,B的层次为2,E的层次为3,K的层次为4。该树的度为3,因为节点最大的为A和D,均有三个子节点。:具有同一父节点的各节点彼此是兄弟节点。即一个节点所拥有的子节点的数量。父节点也是相对的,例如B是E的父节点。图中的叶子节点为K,L,G,I,J。:一个节点含有的子树的根节点。
2024-07-24 20:50:48
791
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人