
Algorithm
henry860916
水滴石穿
展开
-
利用后缀数组 前缀 LCP最长公共前缀求第K大的子串
下面借助一道题目和大家一起讨论:后缀树及后缀数组的问题题目:food所有的组成情况如下:d ffofoofoodoodooood按照字母顺序排列如上所示,先要求第k大的子串,例如第8大子串为oo思路:蛮力就不说了,高级别考试肯定超时。这种题目是典型的利用后缀树和后缀数组解决的。1. 将所有后缀列出来(prefix set)原创 2015-12-30 14:28:41 · 1167 阅读 · 0 评论 -
DP---LCS 最长公共子序列问题
两个字符串CABA 和 BAB,要求找出它们最长的公共子序列。 利用公式:这里有两种情况:1. 求最长公共子序列,不需要连续 2.求最长公共子序列,要求连续原创 2015-12-25 21:04:55 · 222 阅读 · 0 评论 -
图---DFS
DFS是对图进行遍历的最基本的算法,前面将对树的遍历的时候,曾经讲过先序遍历,即根-左子树-右子树,这里DFS和先序遍历比较像。DFS有两种写法:递归,迭代。各有各的好处:递归写法比较简单,但是性能低一些; 迭代写法稍微复杂些,但是性能高一些。大家随情况进行抉择。 递归算法:DFS(G, v) visited[ v ] ← yes for each all w in a原创 2015-12-25 21:48:18 · 344 阅读 · 0 评论 -
图---BFS
BFS是继DFS后对图的又一种遍历方法。大家注意比较BFS算法与DFS的迭代算法,会有惊人的发现~ BFS(G,v) Init queue Add start point v into queue visited[v]=true while queue is not empty t ← deQueue() for each u connected to t if u原创 2015-12-25 22:00:40 · 272 阅读 · 0 评论 -
图---互斥集
互斥集主要用于Kruskal算法中,用于求图的最小生成树。 互斥集主要有3个基本操作: 1. 初始化各个集合Make(a) p[a] ← a 2. 查找各个集合的老祖宗Find(a) if a == p[a] : return a else : return Find(p[a]) 3. 合并两个集合Union原创 2015-12-26 21:05:28 · 930 阅读 · 0 评论 -
图---Prim
求最小生成树主要有两种基本的算法:Prim算法和Kruskal算法。Prim算法主要是着眼于顶点,而Kruskal算法主要是着眼于边。下面介绍Prim算法的过程。 PRIM(G, s) for u in G.V u.key ← ∞ // u.key: 包含U的边中,最短的那条边长 u.π ← NULL // u.π : u的父节点 //初始化起始点 s.k原创 2015-12-26 21:08:45 · 301 阅读 · 0 评论 -
图---Kruskal
前面讲述了Prim算法,这里讲解另一种产生最小生成树的算法:Kruskal算法,该算法对边进行处理。主要分为以下几个步骤:1. 对所有的顶点创建互斥集Make2. 对所有边从小到大排序3. 从第一条边开始,对边的两个顶点进行判定Find: a:如果两个顶点祖宗为同一个,则忽略 b:如果两个顶点祖宗不是同一个,则进行合并操作Union KRUSKAL(G,原创 2015-12-26 21:18:36 · 278 阅读 · 0 评论 -
图---Dijstra
求单源最短路劲用得最多的算法应该就是Dijstra算法了,但是该算法有一个缺点就是不能处理负权,如果遇到负权大家可以参考后面介绍的BellMan Ford算法进行处理。下面介绍下Dijstra算法的主要步骤:1. 初始化集合U,该集合表示已经入选最小的节点集合2. 初始化D,该数组表示源点s到该点的最小距离,没有直接相连则视为无穷大3. 选出距离源点最小距离的点w4. 对直接与原创 2015-12-26 21:33:16 · 303 阅读 · 0 评论 -
图---Floyd
前面介绍过Dijstra算法,该算法主要用于求单源最短路径。对于求任意两点间的最短路径,这里介绍一种新的算法 Floyd。算法比较简单:Floydfor ( int k = 0; k < 节点个数; ++k ){ for ( int i = 0; i < 节点个数; ++i ){ for ( int j = 0; j < 节点个数; ++j ){ if ( Dis[i][原创 2015-12-26 21:38:14 · 260 阅读 · 0 评论 -
图---BFS之从源点到目的点最少拐点问题
1 1 1 1 1 1 1s 0 0 0 0 1 11 0 1 1 0 0 11 0 1 1 1 0 01 0 1 1 1 1 d1 0 0 0 0 0 01 1 1 1 1 1 1从s到d经过最少拐点,每次可以上下左右遍历,遇到1则不可以继续遍历法1:1. 遍历整个矩阵,找出所有第一步的点置为22. 遍历整个矩阵,找出2周围所有点置为2+13. 重复上原创 2015-12-27 16:55:59 · 445 阅读 · 0 评论 -
最拥堵的路段
1->32->33->43->54->65->61. 从1->6 求出每个点的入度x 注:按顺序,小数->大数,3->4计算4的入度,此时3的入度一定已经算出,导向关系:4至少是3的入度,可能大于2. 从6->1 求出每个点的出度y3. 遍历所有的edge,该边经过的次数=edge(a,b) = Xa*Yb a的入度,b的出度例:新地中原创 2015-12-27 17:07:31 · 487 阅读 · 0 评论 -
字符串匹配之boyer moore算法
前面介绍了KMP算法,但是,它并不是效率最高的算法,实际采用并不多。各种文本编辑器的"查找"功能(Ctrl+F),大多采用Boyer-Moore算法。Boyer-Moore算法不仅效率高,而且构思巧妙,容易理解。1977年,德克萨斯大学的Robert S. Boyer教授和J Strother Moore教授发明了这种算法。下面,我根据Moore教授自己的例子来解释这种算法。1.转载 2015-12-30 20:27:39 · 368 阅读 · 0 评论 -
DFS 小结
DFS从实现角度看有两种方法:1. 迭代写法:自己实现一个stack,类似bfs的写法,只不过将queue改成stack而已2. 递归写法:基本框架dfs(){ 1. 退出点,例如到达目的点 2. 剪枝点,优化点,当前耗费已经大于之前得到的Answer 3. 循环体,决策项,例如上下左右等} DFS从题型上划分,有两种类型:原创 2016-07-26 21:02:23 · 811 阅读 · 0 评论 -
算法考试小结
考试步骤:1. 花15分钟阅读题目,题目信息量大的时候需要注意给定的condition2. 花15分钟解析题目,从简单的case开始分析,分析出处理问题的步骤3. 根据解决问题的步骤尝试套用已有算法: @ 是否是单源最短路径题目:djstra @ 是否是多源最短路径: floyd @ 是否含有负权:bellman ford @ 是否是最小生原创 2016-07-26 21:15:50 · 677 阅读 · 0 评论 -
浅谈递归
把每一层递归函数化分为三部分:第一部分:是递归调用前的一些数据处理,判断以及递归结束判断(当然了结束条件肯定在递归调用前,要不每次递归就不会结束了);第二部分:就是递归函数本身了;而第三部分:当然就是递归函数的后续处理代码了!在这里我想我们得想明白一件事情了,每一层的函数都是在上一层递归函数结束时才返回的然后接着处理该层递归函数剩下的部分!不过我觉着最重要的还有一样就是有时候不必刻意去原创 2015-12-26 22:00:44 · 243 阅读 · 0 评论 -
递归之---汉诺塔
递归思想的概念:即将一个复杂问题分解成一系列小的问题,并且这些小问题都具有相同的情形。此时可运用递归的思想来解决更易于理解(但并不一定是效率最高的哦);递归算法有三个关键点:(1)了解题意是否适用递归来解决;(2) 有明确的终止条件(通常是分解出来的一系列小问题里最简单的那种情况); (3) 随着递归算法的演进,数据规模在递减,决定递归执行部分; 设计思路:我们可以原创 2015-12-26 21:56:38 · 280 阅读 · 0 评论 -
鸽巢算法
该算法主要用来对给定数据集进行排序的,可以快速求出第N大的数字,时间为常数时间。缺点:数据的范围不能太大。步骤如下:1. 给定一个待排序数组(相当于一群鸽子),创建一个备用数组(叫鸽巢数组)并初始化元素为0,备用数组的索引(鸽巢的编号)即是待排序数组的值(鸽子的重量)。2. 把待排序数组的值(鸽子),放到数组(鸽巢)里(即用作备用数组的索引)。3. 遍历鸽巢数组,最重的鸽巢编号原创 2015-12-26 21:54:00 · 977 阅读 · 0 评论 -
所有path的总和
例如:求所有path的总和,相连的path的值为乘积2---1: 21---3: 6所有path总和为:2+6+2*6 = 20 公式:2--->1: 1*2*1=2, 1变为叶子:1的新的value=1(1的当前值)+1(2的当前值)*2(path值) = 31--->3: 3*6*1=18,3变为叶子:3的新的value=1(3的当前值)+3(1的原创 2015-12-27 17:33:25 · 278 阅读 · 0 评论 -
DP-----斐波纳契-杨辉三角--素数求法
斐波纳契公式:Fn=Fn-1+Fn-2 杨辉三角:c(r,v)=c(r-1,v-1)+c(r-1,v) 素数求法:从2开始筛选出2~26间的所有素数?1. 筛选出2,删除2n2. 筛选出3,如果3*3>26 则退出,否则删除3n3. 筛选出5,如果5*5>26则退出,否则删除5n4. 筛选出7,如果7*7>26则退出因此,所有筛选出的素数为:2 3原创 2015-12-27 17:19:29 · 521 阅读 · 0 评论 -
图---BellMan Ford
贝尔曼-福特算法的最多运行O(|V|·|E|)次,|V|和|E|分别是节点和边的数量)。该算法是对Dijstra算法的补充,弥补其不能处理负权的缺陷,但是效率不及Dijstra算法。下面是几个基本的步骤: procedure BellmanFord(list vertices, list edges, vertex source) // 该实现读入边和节点的列表,并向两个原创 2015-12-26 21:44:59 · 339 阅读 · 0 评论 -
DP---矩阵连乘问题
矩阵连成问题属于DP问题。主要分三个步骤:假设原数据为ABCD1. 链长从2到N:假设链长为3 2. 根据链长划分区间:则有ABC, BCD 两种区间3. 对每个区间的数据进行切分,从第二个位置切到倒数第二个位置,即A'BC, AB'C, B'CD, BC'D而A,BC,AB,C,B,CD,BC,D前面都已经计算过了。另外注意矩阵连乘的存储方法:存放矩阵链的行列信息原创 2015-12-26 22:09:11 · 391 阅读 · 0 评论 -
二叉搜索
二叉搜索是一种最普遍也是最有效的搜索策略。二叉搜索是基于已经有序的数据集。常用于多点间的引力问题。 具体算法如下:binarysearch( n, data[])start ← 0end ← n - 1while start <= end and location = 0 mid ← start + (end - start) / 2 if data[mid]原创 2015-12-25 20:29:07 · 268 阅读 · 0 评论 -
二叉树的遍历
二叉树有三种典型的遍历方法1. 先序遍历,即先根遍历,根-左子树-右子树先序遍历有点类似DFS算法的过程,尤其于DFS的迭代写法很像,后面会介绍DFS的相关内容。preorder(Tree T) if T is not null visit(T) preorder(T.left) preorder(T.right) 2. 中序遍历,即中根遍历,左子树-根-右子原创 2015-12-25 20:35:24 · 218 阅读 · 0 评论 -
快排
快速排序是目前算法中用得比较多的一种排序方法,一般工程师算法考试中会直接使用冒泡排序,虽然写起来容易,但是效率比较低,不推荐使用。 网上有各种排序方法的介绍及比较,大家可以询问谷哥度娘。这里简单介绍快排的思想,供参考。 quicksort(A[],l,r){ if l<r s=position(A[],l,r) quicksort(A[],l,s-1) quicksor原创 2015-12-24 21:21:50 · 507 阅读 · 0 评论 -
贪心算法
贪心思想 个人更倾向于称贪心为贪心思想,因为它不是一种具体的算法,而是一种思想。所谓贪心,即每次都想要最好的。适合使用贪心思想的算法例如:Prim算法,主要用于求最小生成树,具体算法后面会讨论到。Kruskal算法,主要用于求最小生成树,具体算法后面会讨论到。Dijsktra算法,主要用于求单源最短路径,具体算法后面会讨论到。Huffman tree算法,有待研究。原创 2015-12-24 20:42:21 · 369 阅读 · 0 评论 -
组合问题
组合问题 从ABCD中任意选取2个字符的情况? 法1:常规法任取1个字符的情况: A B C D 基于上面产生的五个子集,从剩余字符中选取第2个字符:B C D A C D A B D原创 2015-12-24 20:22:47 · 358 阅读 · 0 评论 -
位操作在算法中的运用
1. 与操作&100 & 111 = 100 2. 或操作|100 | 000 = 100 3. 异或^100 ^ 000 = 100 4. 取反~~100 = 011 5. 向左移位1即2的2次方,等于4 6. 向右移位>>16>>2 = 00100即16的2的-2次方,等于4 note1:移位和与操作结合,用来原创 2015-12-23 19:46:31 · 441 阅读 · 0 评论 -
排列问题
{1,2,3}的所有排列情况为:123,132,213,231,312,321 六种情况,即3!主要有两种常见的方法来求全排列问题,递归或者迭代法都可以。1. 交换法 每个数字(包括第一个数字)分别与第一个数字交换: 123 213原创 2015-12-23 20:12:10 · 494 阅读 · 0 评论 -
子集subset问题
子集subset问题 字集即组合的集合例如求ABCD的字集,即求ABCD中任取0个的情况+ABCD中任取1个的情况+ABCD中任取2个的情况+ABCD中任取3个的情况+ABCD中任取4个的情况。 遇到字集问题,首先想到暴力求法,即所有元素均有两种情况:取或不取。因此暴力求法可以使用四层for循环解决上述问题。 然而是否有更简单的方法?答案显然是肯定的,即利用前面原创 2015-12-23 20:48:54 · 548 阅读 · 0 评论 -
最大全1子矩阵
1 1 0 00 1 1 00 1 1 00 1 1 0 要求上图中最大的全部是1的子矩阵的大小? step1:每一行从前往后生成连续1的个数 1 2 0 00 1 2 00 1 2 00 1 2 0 step2:K*(上下不小于当前值的元素个数,包含本身) 1 2 0 00 4 6 00 4 6 00 4 6 0例如原创 2015-12-25 21:12:07 · 354 阅读 · 0 评论 -
stack
凡是递归问题都可以转化为迭代的方法进行求解,前提是大家会使用stack。关于stack有两种操作AKA: push 入栈,pop出栈大家对这两种操作都耳熟能详,但是大家是否能熟练写出push,pop的实现过程?考试中没有太多时间让我们去反复推理验证的~push(STACK s, x) top++ if top > stack_size overflow else s(to原创 2015-12-25 21:41:10 · 270 阅读 · 0 评论 -
DP---最长上升/下降子序列
最长上升/下降子序列Seg:1~n个数Status:Si表示以第i个数结尾,从而构成一个最长子序列的长度Policy:第i个数是否加入ak结尾所在的序列StatusChange:Si=max(Si,Sj+1)for i:=1 to n dofor j:=0 to i-1 doif ( a[j]>a[i]) and (opt[j]+1>opt[i]) the原创 2015-12-27 14:21:30 · 306 阅读 · 0 评论 -
DP---求给定矩阵中最大正方形的维度
求给定矩阵中最大正方形的维度dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1;Dp一般自底向上(当前点为右下角),而一般解决问题自顶向下(当前点位左上角)Struct node{ left top left-top min}原创 2015-12-27 14:23:05 · 413 阅读 · 0 评论 -
图---DFS剪枝
DFS剪枝即对DFS进行适当优化,满足条件则退出递归,不需要遍历完所有情况。例如下面出自POJ的题目:TCGGGCAGCCGCGATCATCG这五个串是一个原串的子串,求最小原串的长度?例如答案11:CCGCAGATCGG步骤:1. 计算任意两个串合并后增加的长度 Mer[5][5]2. 对每个子串进行DFS: a 达到N串退出 b 当前原创 2015-12-27 16:24:44 · 782 阅读 · 0 评论 -
DP---源点到目的点经过最多的1点
0 1 0 0 10 0 1 0 01 0 1 1 01 1 0 1 01 0 0 0 1从右下角的1到达最上层经过1点最多?前提:只能向左或向上移动 1 00 11. 先计算右下角2. 计算左下角及右上角(需要的元素已经计算过)3. 计算左上角(需要的元素已经计算过) dp[i,j] = Max(dp[i+1,j], dp[i,j+1])原创 2015-12-27 16:31:23 · 354 阅读 · 0 评论 -
括号层次
求第k层元素的总和,输入为 根(左孩子)(右孩子)4 (4(5(1()())(9(2()(2()()))()))(5(1()(5()()))(1()())))Method1: stack做,因为不需要求所有状态或关系,因此只要求第k层即可,当stack长度为k时则记录数据。Method2: (则+1, ) 则-1原创 2015-12-27 14:19:50 · 2360 阅读 · 0 评论 -
匈牙利算法
匈牙利算法一般应用于二分图的匹配问题。大家可以在网上搜索一篇匈牙利算法之找妹子的文章,个人认为他写得很精彩~算法如下:bool find(int a) { for (int i = 1; i <= n2; i++) { if (data[a][i] == 1 && !state[i]) { //如果节点i与a相邻并且未被查找过 state原创 2015-12-27 13:46:11 · 697 阅读 · 0 评论 -
约瑟夫问题
假设有问题如下:步骤: 1.有牌面上写着从1到N的N张纸牌按照一定的顺序放在桌子上。 2.把此时最上面的一张牌放到纸牌的最下面去。 3.翻开此时最上面的一张牌,出现的是数字“1”。 4.把这张牌放到一边去。 5.把此时最上面的一张牌放到纸牌的最下面去。 6.翻开此时最上面的一张牌,出现的是数字“2”。 7.把这张牌放到一边去。 8.以此类推,每次原创 2015-12-27 13:28:01 · 286 阅读 · 0 评论 -
queue
queue主要应用与BFS的算法中,这里对普通的队列进行介绍。此外还有一种queue叫做priority queue,优先队列应用在后面的Prim算法中,大家可以自己研究下~ 下面对queue的四种基本操作进行介绍,大家最好能够烂熟于胸~1. 入队 enQ(item) if isFull() : exception else rear++ Q[rear]原创 2015-12-25 21:54:49 · 277 阅读 · 0 评论 -
字符串匹配之KMP 算法
举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD"?首先我们想到的应该是brute force法1.首先,字符串"BBC ABCDAB ABCDABCDABDE"的第一个字符与搜索词"ABCDABD"的第一个字符,进行比较。因为B与A不匹配,所以搜索词后移一位。2.因为B与A不匹配,搜索词再往后转载 2015-12-30 20:10:58 · 378 阅读 · 0 评论