Morris算法遍历一棵二叉树,时间复杂度O(n),但是空间复杂度却只用神奇的O(1),下面说一下Morris遍历的流程,首先规定来到的当前结点即为cur 如果cur无左孩子(cur.left == cur = cur.left) 如果mostRight的右孩子指向cur,则让其指向null(mostRight.right = null),同时cur向右移动(cur = cur.right) 先序Morris mostRight.right = null; } cur = cur.right; } System.out.println(); } 中序Morris System.out.println(cur.value + " "); cur = cur.right; } System.out.println(); } 后序Morris
字符串匹配 BF(Brute force)算法 实现:每次向后移动一位进行匹配 RK(Rabin-Karp)算法 实现:将每组要匹配长度的字符串进行hash,再hash后的元素里找 BM(Boyer-Moore )算法 有两部分组成:并且是由大到小,倒着匹配 坏前缀:普通匹配只一位一位移动,移动规则为 si(坏字符的位置) xi(坏字符在匹配字符最后出现的位置) 都没有xi=-1 移动距离等于si-xi KMP(Knuth Morris Pratt)算法 实现:关键部分next数组,失效函数。next数据就是匹配串字符串最长匹配前缀和最长匹配后缀的关系。 KMP算法的Go语言实现代码如下: package main import "fmt" func main() { a := "ababaeabacaaaaaddfdfdfdfdf"
挺好用的,碰到几个问题,有的是瞎试解决了的: 1、我想折线图能够响应单击事件,即点击某个节点后,就能加载进一步的信息,帮助没找到,参照另外一个地方的写法,居然支持事件 Morris.Line }}); }); 2、文字大小调整,hoverFontSize,设置了不太管用,有些浏览器支持有些不行,关键是,微信小程序的浏览器不行,于是改了两个地方: 1)morris.css 中的样式,改了似乎用处不大 2)分析页面,找到样式,直接用jquery设置 $(".morris-hover morris-default-style").css({"font-size":"24px"
莫里斯算法与线索二叉树有异曲同工之妙,建议先了解线索二叉树,再来学习 ---- Morris算法 莫里斯算法思想 前序遍历 中序遍历 后序遍历 ---- 莫里斯算法思想 mirror遍历用到了线索二叉树的思想 ,在Morris方法中不需要为每个节点额外分配指针指向其前(predecessor)和后继节点(successor),只需要利用叶子节点中的左右空指针指向某种顺序遍历下的前驱节点或后继节点就可以了 。 Morris的整体思路就是将 以某个根结点开始,找到它左子树的最右侧节点之后与这个根结点进行连接 我们可以从 图2 看到,如果这么连接之后,cur 这个指针是可以完整的从一个节点顺着下一个节点遍历,将整棵树遍历完毕 到此为止,左子树部分就已经处理完毕了,下面右子树 总结: 连接过程:先连接后左移 复原过程:先右移后斩断,若斩断位置到位,立刻执行斩断,如果位置不到位,通过while循环到达指定位置 前序遍历 Morris
输入:root = [] 输出:[] 示例 3: 输入:root = [1] 输出:[1] 提示: 树中节点数目在范围 [0, 100] 内 -100 <= Node.val <= 100 进阶: 递归算法很简单 ,你可以通过迭代算法完成吗?
Morris算法 这个算法每个结点需要遍历2次,所以时间复杂度要比之前两种高一些,但是空间复杂度仅为 O(1) 。 盗了一张示意图,出处见水印。 算法核心为:每个结点要经过两遍,第一次经过要找出当前结点左子树的最右结点的位置,然后把它的右指针指向自己;第二次经过时会发现它左子树的最右结点已经指向了自己,说明左子树已经全部遍历完,通过最右结点的右指针走了回来
kmp算法 这篇文章主要是总结一下kmp算法。所以就不写暴力遍历的逻辑了。 这个算法属实是让我看了挺长时间,各种讲解博客是一点也看不进去(不是写的不详细,而是总感觉写的乱七八糟很复杂),最长公共前缀一直没理解其作用,不过反反复复的刷对应的讲解视频,卒或有所闻。 因为这个算法属实是有点抽象的,怪不得都说编程的尽头是数学,所以只是单纯的看文章中的文字可能有点痛苦,但是,don’t worry,结合代码,结合图片,多看几遍,卒或有所闻。 首先,kmp算法主要是用来判断模式串是否在文本串中出现过,如果出现过,则返回最早出现的位置的经典算法。 该算法由 Donald Knuth、Vaughan Pratt、James H. Morris 三人于 1977 年联合发表,算法也是由这三人姓氏进行命名。
一、中序遍历 public static void morrisIn(TreeNode root) { if (root == null) return; TreeNode cur = root; TreeNode mostRight = null; while (cur != null){ if (cur.left != null){ mostRight = cur.left; while (mostRight
在学习二叉树的遍历的时候,有一个大名鼎鼎的Morris算法,使用双指针就可以实现二叉树的前中后序遍历,并且时间复杂度是O(N),空间复杂度是O(1),于是我使用Golang实现一个可存放重复元素的二叉搜索树 ,并且结合Morris算法进行查找。 res.Val) return node } // 获取中序遍历的结果, 就知道是否是有序的 func (this *Bst_1) GetSortedSequence() []int { // Morris 算法 res := []int{} p1 := this.root var p2 *TreeNode for p1 !
字符串匹配可以采用多种算法,包括朴素模式匹配算法、KMP(Knuth-Morris-Pratt)算法、Boyer-Moore算法等。 这些算法的性能和效率各不相同,具体选择取决于应用的需求和文本数据的规模。 0. 朴素模式匹配算法 朴素模式匹配算法:【数据结构】数组和字符串(十四):字符串匹配1:朴素的模式匹配算法(StringMatching) 朴素模式匹配算法的优点是过程简单,缺点是效率低。 在最坏情况下,该算法要匹配n-m+1次,每次匹配要做m次比较。本文将介绍更高效的模式匹配算法——KMP算法 1. ADL语言 2. KMP算法分析 待完善 3. } printf("KMP算法:比较次数: %d\n", comparisons); return 0; } 6.
如果cur == null 停止遍历 Morris:1242513637 1 public static void morris(TreeNode head){ 2 if( 先序遍历 Morris:1242513637 Morris先序:1245367 基于Morris的先序遍历,如果一个节点可以到达两次则打印第一次,如果只能到达一次直接打印。 :1242513637 Morris中序:4251637 基于Morris的中序遍历,如果一个节点可以到达两次则打印第二次,如果只能到达一次直接打印。 :1242513637 Morris先序:4526731 基于Morris的后序遍历,如果一个节点可以到达两次则第二次到达时逆序打印左树的右边界,单独逆序打印整棵树的右边界。 当不需要整合左树和右树信息的时候,可以用树型DP,但是Morris是最优解。
KMP算法,Knuth-Morris-Pratt Algorithm,一种由Knuth(D.E.Knuth)、Morris(J.H.Morris)和Pratt(V.R.Pratt)三人提出的一种快速模式匹配算法 KMP算法 KMP算法,是由KMP朴素算法演变而来的,主要分为两步: 第一步,当字符串比较出现不等时,确定下一趟比较前,应该将子串pattern右移多少个字符(预处理) 第二步,子串pattern右移后 总结: 第一步,其实就是KMP朴素算法对模式匹配子串pattern的预处理过程,上面已经给出了算法公式和代码示例 第二步,本质上就是KMP朴素算法,不同的仅仅是pattern右移的位数大小由其预处理过程决定 代码下载 参考推荐: KMP(百度百科) Knuth-Morris-Pratt algorithm(Wikipedia) Knuth-Morris-Pratt algorithm(String Matching ) Knuth-Morris-Pratt string matching
优点: 暴力查找算法:实现简单且在一般情况下工作良好(Java的String类型的indexOf()方法就是采用暴力子字符串查找算法); Knuth-Morris-Pratt算法能够保证线性级别的性能且不需要在正文中回退 ; Boyer-Moore算法的性能一般情况下都是亚线性级别; Rabin-Karp算法是线性级别; 缺点: 暴力查找算法所需时间可能和NM成正比; Knuth-Morris-Pratt算法和Boyer-Moore 算法需要额外的内存空间; Rabin-Karp算法内循环很长(若干次算术运算,其他算法都只需要比较字符); 各种字符串查找算法实现的成本总结 算法 版本 最坏情况 一般情况 是否回退 正确性 额外空间需求 暴力算法 -- MN 1.1N 是 是 1 KMP算法 完整的DFA(博客中实现的方法) 2N 1.1N 否 是 MR 仅构造不匹配的状态转换 3N 1.1N 否 是 M 完整版本 3N N/M 是 是 R Boyer-Moore算法 启发式查找不匹配字符 MN N/M 是 是 R Rabin-Karp算法 蒙特卡洛算法 7N 7N 否 是* 1 拉斯维加斯算法 7N* 7N 是 是 1 *
Knuth-Morris-Pratt 字符串查找算法,简称为 “KMP算法”,常用于在一个文本串S内查找一个模式串P 的出现位置,这个算法由Donald Knuth、Vaughan Pratt、James Morris三人于1977年联合发表,故取这3人的姓氏命名此算法。 As a result, the complexity of the searching phase of the Knuth-Morris-Pratt algorithm is in O(n). Since mless or equaln, the overall complexity of the Knuth-Morris-Pratt algorithm is in O(n). KMP源代码 极简版本的 KMP 算法源代码: next数组首位用-1来填充,这样在处理长度的时候,思维上不会很绕。
后继者[1] 题目描述 设计一个算法,找出二叉搜索树中指定节点的“下一个”节点(也即中序后继)。 如果指定节点没有对应的“下一个”节点,则返回 null。 一般树+Morris遍历 如果看过我前两天的一道关于二叉搜索树的题解: 【每日算法Day 73】学妹大半夜私聊我有空吗,然后竟然做出这种事! 韦阳的博客:【每日算法Day 73】学妹大半夜私聊我有空吗,然后竟然做出这种事![2] 知乎专栏:【每日算法Day 73】学妹大半夜私聊我有空吗,然后竟然做出这种事! [3] 那么你一定会知道这个 Morris 遍历算法,用常数空间来解决结点无法访问父结点的问题。这里就不细讲了,请直接看之前的题解。 方法是一样的,用 Morris 遍历得到中序遍历,然后遍历一遍找到 p ,输出它的下一个结点就行了。
KMP由来 上一节说的BM算法是最高效、最常用的字符串匹配算法。 最知名的却是KMP,它3位作者(D.E.Knuth,J.H.Morris,V.R.Pratt),算法的全称是Knuth Morris Pratt 算法,简称KMP算法。 2. KMP算法基本原理 类似于BM里的概念:坏字符(不能匹配的),好前缀(已经匹配的那段) ? ? KMP算法目的:当遇到坏字符后,对于已经对比过的好前缀,将模式串多滑动几位 ? 代码 王争的代码不好理解,找了书和别的人的代码参考 /** * @description: KMP字符串匹配算法 * @author: michael ming * @date: 2019/6/22
福哥答案2021-02-03: Knuth-Morris-Pratt 字符串查找算法,简称为 KMP算法,常用于在一个文本串 S 内查找一个模式串 P 的出现位置。 这个算法由 Donald Knuth、Vaughan Pratt、James H. Morris 三人于 1977 年联合发表,故取这 3 人的姓氏命名此算法。 下面直接给出 KMP算法 的操作流程: 1.假设现在文本串 S 匹配到 i 位置,模式串 P 匹配到 j 位置。 实现 strStr() 左神的KMP算法的java代码,我的golang代码参考了这个
本文是介绍 什么是 BF算法、KMP算法、BM算法 三部曲之一。 KMP算法 内部涉及到的数学原理与知识太多,本文只会对 KMP算法 的运行过程、 部分匹配表 、next数组 进行介绍,如果理解了这三点再去阅读其它有关 KMP算法 的文章肯定能有个清晰的认识。 以下的文字描述请结合视频动画来阅读~ 定义 Knuth-Morris-Pratt 字符串查找算法,简称为 KMP算法,常用于在一个文本串 S 内查找一个模式串 P 的出现位置。 这个算法由 Donald Knuth、Vaughan Pratt、James H. Morris 三人于 1977 年联合发表,故取这 3 人的姓氏命名此算法。 后记 市面上好多讲解 KMP算法 的文章的写的太混乱了,很多人因此产生了恐惧,这一章目的就是为了能让大家能大概理解 KMP算法 的运行过程,不会畏惧 KMP算法 。
很早之前就被人给专研出来了,也就是本文的主角:Morris Traversal Morris Traversal 因为它由 Joseph Morris 发明的,所以叫 Morris Traversal 先序遍历 我们对比下 先序序列 和 Morris 序列 发现了什么? Morris Traversal 第二次到达的节点不打印,就是 先序序列 了 代码也就手到擒来了 中序遍历 我们对比下 中序序列 和 Morris 序列 只会遍历一次的节点,直接打印 ;会遍历两次的节点,第一次的时候不打印,第二次打印,就得到了 中序序列 代码很容易撸出来了 后序遍历 对比 后序序列 和 Morris 序列 一眼看不出有什么关系 通过 Morris 我们来看代码 总结 额外空间复杂度 只用到了有限几个变量, Morris Traversal 额外空间复杂度 O(1) 时间复杂度 Morris Traversal 时间复杂度是不是
} } res.add(list); } return res; } } 三、Morris Morris 遍历的实质就是避免利用栈结构,让下层节点拥有指向上层的指针,具体是通过让底层节点指向 null 的空闲指针指向上层的某个节点,到达子节点指向父节点的效果。 详情可参考该博客, morris 方法日后有时间再研究。 Morris 算法进行二叉树遍历