⑴ kmp算法什么意思
KMP算法之所以叫做KMP算法是因为这个算法是由三个人共同提出来的,就取三个人名字的首字母作为该算法的名字。其实KMP算法与BF算法的区别就在于KMP算法巧妙的消除了指针i的回溯问题,只需确定下次匹配j的位置即可,使得问题的复杂度由O(mn)下降到O(m+n)。
在KMP算法中,为了确定在匹配不成功时,下次匹配时j的位置,引入了next[]数组,next[j]的值表示P[0...j-1]中最长后缀的长度等于相同字符序列的前缀。
对于next[]数组的定义如下:
1) next[j] = -1 j = 0
2) next[j] = max(k): 0<k<j P[0...k-1]=P[j-k,j-1]
3) next[j] = 0 其他
如:
P a b a b a
j 0 1 2 3 4
next -1 0 0 1 2
即next[j]=k>0时,表示P[0...k-1]=P[j-k,j-1]
因此KMP算法的思想就是:在匹配过程称,若发生不匹配的情况,如果next[j]>=0,则目标串的指针i不变,将模式串的指针j移动到next[j]的位置继续进行匹配;若next[j]=-1,则将i右移1位,并将j置0,继续进行比较。
⑵ 回溯算法的经典书籍
《算法导论》Thomas H.Cormen、Charles E.Leiserson、Ronald L.Rivest、Clifford Stein着 潘金贵、顾铁成、李成法、叶懋译. -北京:机械工业出版社,2006.9
《计算机算法设计与分析》王晓东编着. —3版. -北京:电子工业出版社,2007.5
⑶ 怎么提高编程能力逻辑思维能力
思考问题的方式,方向,解决问题的方法,也就是说应该从哪里入手,从哪里着手去解决问题。
每个人都是从零基础开始接触编程的,很多技术大牛总结了很多经验、解决问题的方式。而现在作为一个编程初学者,我们不需要重新造轮子。我们只需要跟随前辈们脚步,避免重复去走他们已经走过的弯路,也可以说我们现在做的一切都是站在巨人的肩膀来进行的。学习前辈们的经验和解决问题的方式,然后结合自身来解决自己的问题,最终融会贯通为自己所用。
建议大家,解决问题的时候,首先要把问题分解。大化小,很多小问题已经有了非常成熟的解决方案,搜索引擎可以解决大部分问题,我们直接拿来用就可以了,并且记住这种解决问题的方案。而剩下解决不了的小问题,我们在进行针对性解决,每一个小问题解决后,一整块大问题就随之解决。
编程思维的训练就是要学习成熟的解决问题的方法:比如if
语句用来做分支判断,循环用来解决反复运算的问题。穷举法、递推、递归、排序、回溯等等(如果需要当专业程序员,需要学习数据结构和算法,设计模式等等,需要学的东西很多很多。但首先要解决的一个问题是自己能写代码解决一般问题。)
训练函数抽象,类抽象解决问题。如对有序数组,查找特定数值,没有经过训练,初学者,直接用循环遍历。如果经过二分法算法的训练,下次碰到这样的问题,就用二分法求解。
(需求->需求分析->设计->编码->测试->交付等)
拿到一个习题,还没有进行分析,就马上敲代码,这个学习方式,是不好的学习方式。
再设计,用哪种数据类型(数据结构)来组织或保存数据,用何种算法来计算效率最高,用面向过程,还是面向对象的编程范式,还是用函数式编程等等。设计后,再编写代码,最后写测试。
如果大家对于学习编程有任何疑问,可以随时咨询我,这是我的V:Zhanlaoshi71 从事IT行业16年,精通八种语言,多跟专业的人交流学习。
只有先经过训练常见的算法,分解问题,会做需求分析,慢慢训练,才会养成自己的思路。没有人一出生会编程,只有经过训练,才会学会编程。很多牛逼程序员用vim,敲的啪啪响,一会儿一屏幕代码,为啥那么熟练使用vim,习惯成自然。当你训练多了以后,学会一定的套路(解决问题的方法),养成独立思考的习惯,假以时日,自然就有思路了。
养成独立思考的习惯,养成切分问题,养成大问题化解小问题,养成套用学过的算法,才会有思路。简单的判断、循环都不会写,就想玩django,何来的思路?
万丈高楼从地起,希望大家脚踏实地实地的从基础训练起,先达到独立写代码解决一般的问题,再谈项目。见过盲目上号称牛逼项目的培训班出来的程序员,
没有学会独立写代码解决一般的问题的能力,开发项目时如狗咬刺猬无从下手。
⑷ 除贪心算法外 还有哪些算法
你指的是算法设计的技巧和方法吧~
这些多了
比如最简单的归纳法(例如递归求整数幂、horner规则的二项式求值等等),万能的回溯法(本质上即穷举搜索,能解决大部分的枚举类问题,如8皇后),高效的动态规划(“填表格法”,能将许多最优解问题以极快时间内解决,典型例子如背包问题的动态规划求解),还有很多(分支定界,分治,深度和广度优先遍历,随机算法,近似算法等等)不过这些是最基础的算法知识了……贪心属于最先割技术,每次求出当前条件下的最优解,这方面可以参考《算法导论》及《算法设计与分析》等相关书籍,相信能有不少收获。
⑸ B树算法难么
感觉挺难。
B树的定义
假设B树的度为t(t>=2),则B树满足如下要求:(参考算法导论)
(1) 每个非根节点至少包含t-1个关键字,t个指向子节点的指针;至多包含2t-1个关键字,2t个指向子女的指针(叶子节点的子女为空)。
(2) 节点的所有key按非降序存放,假设节点的关键字分别为K[1], K[2] … K[n], 指向子女的指针分别为P[1], P[2]…P[n+1],其中n为节点关键字的个数。则有:
P[1] <= K[1] <= P[2] <= K[2] …..<= K[n] <=P[n+1] // 这里P[n]也指其指向的关键字
(3) 若根节点非空,则根节点至少包含两个子女;
(4) 所有的叶子节点都在同一层。
B树的搜索,search(root, target)
从root出发,对每个节点,找到大于或等于target关键字中最小的K[i],如果K[i]与target相等,则查找成功;否则在P[i]中递归搜索target,直到到达叶子节点,如仍未找到则说明关键字不在B树中,查找失败。
B树的插入,insert(root,target)
B树的插入需要沿着搜索的路径从root一直到叶节点,根据B树的规则,每个节点的关键字个数在[t-1, 2t-1]之间,故当target要加入到某个叶子时,如果该叶子节点已经有2t-1个关键字,则再加入target就违反了B树的定义,这时就需要对该叶子节点进行分裂,将叶子以中间节点为界,分成两个包含t-1个关键字的子节点,同时把中间节点提升到该叶子的父节点中,如果这样使得父节点的关键字个数超过2t-1,则要继续向上分裂,直到根节点,根节点的分裂会使得树加高一层。
上面的过程需要回溯,那么能否从根下降到叶节点后不回溯就能完成节点的插入呢?答案是肯定的,核心思想就是未雨绸缪,在下降的过程中,一旦遇到已满的节点(关键字个数为2t-1),就就对该节点进行分裂,这样就保证在叶子节点需要分裂时,其父节点一定是非满的,从而不需要再向上回溯。
B树的删除,delete(root,target)
在删除B树节点时,为了避免回溯,当遇到需要合并的节点时就立即执行合并,B树的删除算法如下:从root向叶子节点按照search规律遍历:
(1) 如果target在叶节点x中,则直接从x中删除target,情况(2)和(3)会保证当再叶子节点找到target时,肯定能借节点或合并成功而不会引起父节点的关键字个数少于t-1。
(2) 如果target在分支节点x中:
(a) 如果x的左分支节点y至少包含t个关键字,则找出y的最右的关键字prev,并替换target,并在y中递归删除prev。
(b) 如果x的右分支节点z至少包含t个关键字,则找出z的最左的关键字next,并替换target,并在z中递归删除next。
(c) 否则,如果y和z都只有t-1个关键字,则将targe与z合并到y中,使得y有2t-1个关键字,再从y中递归删除target。
(3) 如果关键字不在分支节点x中,则必然在x的某个分支节点p[i]中,如果p[i]节点只有t-1个关键字。
(a) 如果p[i-1]拥有至少t个关键字,则将x的某个关键字降至p[i]中,将p[i-1]的最大节点上升至x中。
(b) 如果p[i+1]拥有至少t个关键字,则将x个某个关键字降至p[i]中,将p[i+1]的最小关键字上升至x个。
(c) 如果p[i-1]与p[i+1]都拥有t-1个关键字,则将p[i]与其中一个兄弟合并,将x的一个关键字降至合并的节点中,成为中间关键字。