本文共 5826 字,大约阅读时间需要 19 分钟。
输入一棵二叉树,判断该二叉树是否是平衡二叉树。
平衡二叉树:每个子树的深度之差不超过1
后续遍历二叉树,在遍历二叉树每个节点前都会遍历其左右子树
比较左右子树的深度,若差值>1则返回一个标记-1表示当前子树不平衡
若左右子树存在一个不平衡或左右子树差值大于1,则整棵树不平衡
若左右子树平衡,则返回当前树深:左右子树最大深度+1
function IsBalanced_Solution(pRoot) { return balanced(pRoot) != -1;}function balanced(node) { //空树,平衡,树深0 if (!node) { return 0; } //判断左子树 const left = balanced(node.left); //判断右子树 const right = balanced(node.right); //判断是否平衡 if (left === -1 || right === -1 || Math.abs(left - right) > 1) { return -1; } //如果平衡,返回树深 return Math.max(left, right) + 1;}
输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。
套用回溯算法的思路
设定一个结果数组result来存储所有符合条件的路径
设定一个栈stack来存储当前路径中的节点
设定一个和sum来标识当前路径之和
function FindPath(root, expectNumber) { //存储路径结果 const result = []; if (root) { FindPathCore(root, expectNumber, [], 0, result); } return result;}function FindPathCore(node, expectNumber, stack, sum, result) { //记录下当前走的节点 stack.push(node.val); sum += node.val; if (!node.left && !node.right && sum === expectNumber) { result.push(stack.slice(0)); } //走左右两个方向 if (node.left) { FindPathCore(node.left, expectNumber, stack, sum, result); } if (node.right) { FindPathCore(node.right, expectNumber, stack, sum, result); } //两个方向都走完了,无路可走,回溯。 //此处pop是为了从stack中删除该节点,不要占位置。 stack.pop();}
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
解析:
在二叉搜索树中,每个结点都有两个分别指向其左、右子树的指针,左子树结点的值总是小于父结点的值,右子树结点的值总是大于父结点的值。在双向链表中,每个结点也有两个指针,它们分别指向前一个结点和后一个结点。所以这两种数据结构的结点是一致,二叉搜索树和双向链表,只是因为两个指针的指向不同而已,通过改变其指针的指向来实现是完全可能的。
为了减少指针的变换次数,并让操作更加简单,在转换成排序双向链表时,原先指向左子结点的指针调整为链表中指向前一个结点的指针,原先指向右子结点的指针调整为链表中指向下一个结点的指针。 由于要求链表是有序的,可以借助二叉树中序遍历,因为中序遍历算法的特点就是从小到大访问结点。当遍历访问到根结点时,假设根结点的左侧已经处理好,只需将根结点与上次访问的最近结点(左子树中最大值结点)的指针连接好即可。进而更新当前链表的最后一个结点指针。同时中序遍历过程正好是转换成链表的过程,可采用递归方法处理。二叉搜索树的中序遍历即排序后的序列,故代码步骤如下:
function Convert(pRootOfTree) { //如果空树,返回空链表 if (!pRootOfTree) { return null; } //转换成双向链表 ConvertCore(pRootOfTree); //向前移动到第一个节点 while (pRootOfTree.left) { pRootOfTree = pRootOfTree.left; } return pRootOfTree;}function ConvertCore(node, last) { //递归左子树,获取左子树的最后一个结点 if (node.left) { last = ConvertCore(node.left, last) } //根节点指向左子树最后一个结点 node.left = last; //实现双向指针 if (last) { //左子树最后一个结点指向根节点 last.right = node; } //last记录新节点 last = node; //递归右子树,获取右子树的最后一个节点 if (node.right) { last = ConvertCore(node.right, last); } //返回记录节点 return last;}
请实现两个函数,分别用来序列化和反序列化二叉树
//序列化function Serialize(pRoot, arr = []) { //空 if (!pRoot) { arr.push('#'); } else { //中左右 arr.push(pRoot.val); Serialize(pRoot.left, arr) Serialize(pRoot.right, arr) } //以逗号分隔 return arr.join(',');}//反序列化function Deserialize(s) { //字符串为空 if (!s) { return null; } //split() 方法用于把一个字符串分割成字符串数组。 return deserialize(s.split(','));}function deserialize(arr) { let node = null; //取出第一个元素 const current = arr.shift(); //节点不为空 if (current !== '#') { //根节点 node = { val: current } //左右子树 node.left = deserialize(arr); node.right = deserialize(arr); } return node;}
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
中序遍历的顺序 左 - 根 - 右
所以寻找下一个节点的优先级应该反过来 优先级 右 - 根 - 左
以下图的二叉树来分析:
中序遍历: CBDAEF
function GetNext(pNode) { //空 if (!pNode) { return null; } //右节点不空 if (pNode.right) { pNode = pNode.right; //取右节点的最左侧节点 while (pNode.left) { pNode = pNode.left; } return pNode; } else { while (pNode) { //没有父节点 if (!pNode.next) { return null; //该节点为父节点左节点 } else if (pNode == pNode.next.left) { return pNode.next; } //该节点为父节点的右节点,则向上层寻找 pNode = pNode.next; } return pNode; }}
输入两棵二叉树A
,B
,判断B
是不是A
的子结构。(ps:我们约定空树不是任意一个树的子结构)
首先找到A
树中和B
树根节点相同的节点
从此节点开始,递归AB
树比较是否有不同节点
function HasSubtree(pRoot1, pRoot2) { let result = false; //均不空 if (pRoot1 && pRoot2) { //根节点相同 if (pRoot1.val === pRoot2.val) { //比较两者 result = compare(pRoot1, pRoot2); } //没找到时进行查找 if (!result) { //比较A的右子树与B树 result = HasSubtree(pRoot1.right, pRoot2); } if (!result) { //比较A的左子树与B树 result = HasSubtree(pRoot1.left, pRoot2); } } return result;}function compare(pRoot1, pRoot2) { if (pRoot2 === null) { return true; } if (pRoot1 === null) { return false; } //根节点不一样,返回 if (pRoot1.val !== pRoot2.val) { return false; } //根节点一样,左子树与左子树比较,右子树与右子树比较 return compare(pRoot1.right, pRoot2.right) && compare(pRoot1.left, pRoot2.left);}
转载地址:http://wlqmz.baihongyu.com/