最需要注意的是二叉树。二叉树深度优先搜索3种遍历方式:functiondfs(root){if(!root)return//前序遍历dfs(root.left)//中序遍历dfs(root.right)//后序遍历ordertraversal}中序遍历的定义,如果输入二叉树的根节点不为空,先遍历它的左子树,再遍历根节点,最后遍历右子树。不管是深度优先搜索算法,无论是递归代码还是迭代代码,如果二叉树有n个节点,那么它们的时间复杂度都是O(n)。如果二叉树的深度是h,那么它们的空间复杂度就是O(h)。在二叉树中,二叉树的深度h的最小值为log2(n+1),最大值为n。比如一棵包含7个节点的二叉树,至少有3层(二叉树第一层有1个节点,第二层有2个节点,第三层有4个节点),但最多可能有7层(二叉树中除叶子节点外,其他每个节点只有1个子节点)。面试题47:二叉树剪枝题目:一棵二叉树中所有节点的值不是0就是1,请剪掉二叉树中所有节点的值都为0的子树。varpruneTree=function(root){if(root==null)returnnull;根。left=pruneTree(root.left)根。right=pruneTree(root.right)if(root.left==null&&root.right==null&&root.val==0){returnnull}returnroot};/***@param{TreeNode};root*@return{TreeNode}*/varpruneTree=function(root){constres=dfs(root)if(res==0)returnnull;返回根};vardfs=function(root){if(!root)return0letleft=dfs(root.left)letright=dfs(root.right)constres=root.val+dfs(root.left);+dfs(root.right)if(left==0){root.left=null}if(right==0){根。right=null}返回root。val+left+right;}varpruneTree=function();root){if(root==null)返回null;根。left=pruneTree(root.left)根。right=pruneTree(root.right)if(root.left==null&&root.right==null&&root.val==0){returnnull}返回根};上面的代码本质上实现了递归的后序遍历。每当遍历一个节点,如果节点满足条件,则删除该节点。由于是后序遍历,首先在根节点root的左右子树上递归调用函数pruneTree,删除左右子树中节点值全为0的子树。只有当根的左右子树都为空,且自身的值也为0时,才能删除这个节点。所谓删除节点,就是将null返回给它的父节点,使该节点从二叉树中消失。二叉树的序列化与反序列化题目:请设计一种算法,将二叉树序列化为字符串,将字符串反序列化为原始二叉树的算法。从根节点到叶节点的路径数字之和/***定义一个二叉树节点。*functionTreeNode(val){*this.val=val;*this.left=this.right=null;*}*//***将树编码为单个字符串。**@param{TreeNode}root*@return{string}*/varserialize=function(root){returnrserialize(root,'');};varrserialize=function(root,str){if(root==null){str+="无,"}else{str+=root.val+''+",";str=rserialize(root.left,str)str=rserialize(root.right,str)}returnstr}/***将编码数据解码为树。**@param{string}数据*@return{TreeNode}*/vardeserialize=function(data){constdataArray=data.split(",");返回rdeserialize(dataArray);};varrdeserialize=(dataList)=>{if(dataList[0]==="None"){dataList.shift();返回空值;}constroot=newTreeNode(parseInt(dataList[0]));数据列表.shif吨();root.left=rdeserialize(dataList)root.right=rdeserialize(dataList)returnroot;}从根节点到叶节点的路径数之和varsumNumbers=function(root){returndfs(root,0)};vardfs=函数(根,路径){如果(根==null)返回0;path=path*10+root.valif(root.left==null&&root.right==null){returnpath}returndfs(root.left,path)+dfs(root.right,path)}求和下行路径的节点值的数量题目:给定一棵二叉树和一个值和,求二叉树中节点值的和等于sum路径的数量路径的定义是节点是在二叉树中沿着指向子节点的指针向下移动,但不一定从根节点开始,也不一定到叶子节点结束。例如图8.5所示的二叉树,两条路径的节点值之和等于8,其中第一条路径从节点5开始经过节点2到节点1,第二条路径开始从节点2到节点6。/***@param{TreeNode}root*@param{number}targetSum*@return{number}*/varpathSum=function(root,targetSum){if(root==null){return0;}letret=rootSum(root,targetSum);ret+=pathSum(root.left,targetSum);ret+=pathSum(root.right,targetSum);返回ret;};constrootSum=(root,targetSum)=>{让ret=0;如果(根==空){返回0;}constval=root.val;如果(val===targetSum){ret++;}ret+=rootSum(root.left,targetSum-val);ret+=rootSum(root.right,targetSum-val);returnret;}节点值和最大的路径题目:在二叉树中,一条路径被定义为沿着节点所有节点之间的连线从任意节点到任意节点的路径。该路径至少包含一个节点,不一定经过二叉树的根节点,也不一定经过叶子节点。给定一棵非空二叉树,求二叉树所有路径上节点值之和的最大值。例如,在图8.6所示的二叉树中,从节点15到节点7经过节点20的路径的节点值之和为42,这是节点值之和最大的路径。varmaxPathSum=function(root){letmaxSum=[-Infinity]dfs(root,maxSum)returnmaxSum[0]};vardfs=function(root,maxSum){if(root==null)return0letmaxSumLeft=[-Infinity]letmaxSumRight=[-Infinity]letleft=Math.max(0,dfs(root.left,maxSumLeft))letright=Math.max(0,dfs(root.right,maxSumRight))maxSum[0]=Math.max(maxSumLeft[0],maxSumRight[0]);maxSum[0]=Math.max(maxSum[0],root.val+left+right)returnroot.val+Math.max(left,right)}二叉搜索树二叉搜索树是一种特殊的二叉树,它的左子节点总是小于或等于根节点,它的右子节点总是大于或等于根节点。三种不同的二叉树深度优先搜索算法都适用于二叉搜索树,但是中序遍历是解决二叉搜索树相关面试题最常用的思路,因为中序遍历遍历的是二叉搜索树中的两个节点增加节点值的顺序fork搜索树的每个节点varsearchBST=function(root,val){letcur=rootwhile(cur!=null){if(cur.val==val){break;}if(cur.val
