【秋招刷题】二叉树系列

二叉树中和为某一值的路径

描述:
输入一颗二叉树的根节点root和一个整数expectNumber,找出二叉树中结点值的和为expectNumber的所有路径。
1.该题路径定义为从树的根结点开始往下一直到叶子结点所经过的结点
2.叶子节点是指没有子节点的节点
3.路径只能从父节点到子节点,不能从子节点到父节点
4.总节点数目为n
如二叉树root为{10,5,12,4,7},expectNumber为22
在这里插入图片描述
示例:
输入:{10,5,12,4,7},22
返回值:[[10,5,7],[10,12]]
说明:返回[[10,12],[10,5,7]]也是对的

题目分析:这个题需要找到所有的叶子节点,且在找打过程中要记录路径上的节点,将符合条件的路径放入到结果数组里面。既然需要递归,就要有结束条件,结束条件就是子节点以及结点值的和为expectNumber。

下面这个是我的答案:

  • 首先排出异常情况,当输入的root是空的时候
  • 定义一个数组,用来存放经过的节点。
  • 正向加加,每遇到一个节点就加上这个节点的值。
  • 进行递归,如果左孩子有,就将左孩子节点作为下一个递归的root节点。左孩子递归完了就会去找右孩子节点。如果右孩子存在那么就将右孩子作为下一次递归的root节点。
  • 每次递归结束的条件是,如果当前节点是叶子节点的话就要return返回,但是如果这个时候num的值还等于要求的整数值,此时就要把当前List列表中的值放入到result中去。
function FindPath(root, expectNumber)
{
    if(!root) return [];
    let result=[];
    var stack=function (root , num,list){
       num+=root.val;
        list.push(root.val)
        if(!root.left&&!root.right&&expectNumber==num){
            result.push([...list]);return;
        }else if(!root.left&&!root.right) return;
        if(root.left){
            stack(root.left,num,list);list.pop()
        }
        if(root.right){
            stack(root.right,num,list);list.pop()
        }
    }
    stack(root,0,[]);
    return result;
    
}

优秀答案:
人家这个答案就很巧妙,是当每次遍历一个节点的时候,就在目标整数上减去当前节点的值。结束的条件正好是当前叶子节点的值等于减去后剩下的那个值。

let res=[];
let path=[];
function FindPath(root, expectNumber)
{
     if(!root){
         return res;
     }
     dfs(root,expectNumber);
     return res;
}
 
function dfs(root,target){
    path.push(root.val);
    if(!root.left && !root.right && target==root.val){
        res.push([...path]);
    }
    target = target-root.val;
    if(root.left){
        dfs(root.left,target);
    }
    if(root.right){
        dfs(root.right,target);
    }
    path.pop();
}

(继续下一道)

二叉搜索树与双向链表

描述:
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。如下图所示
在这里插入图片描述
注意:
1.要求不能创建任何新的结点,只能调整树中结点指针的指向。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继
2.返回链表中的第一个节点的指针
3.函数返回的TreeNode,有左右指针,其实可以看成一个双向链表的数据结构
4.你不用输出双向链表,程序会根据你的返回值自动打印输出
输入:
{10,6,14,4,8,12,16}
返回值:
From left to right are:4,6,8,10,12,14,16;From right to left are:16,14,12,10,8,6,4;
说明:
输入题面图中二叉树,输出的时候将双向链表的头节点返回即可。

分析:这道题真的上来就是头晕,因为涉及到了双向链表还有树。最左边的叶子节点是起点,最右边的叶子节点是终点,除此之外比如说树节点,他的左右指针就不是左右节点了,他的左指针是左子树的最后边的节点,右指针是右子树最右边的那个节点。万一中间还有更多向根节点这种类型的怎么办?,所以我就稍稍看了一下别人的思路,哈哈哈哈(实在是没思路)。后来恍然大悟。这不就是中序遍历嘛,我去!最后生成的链表从左到右的排列顺序就是中序遍历的结果。这就好办了。下面是我的代码。
解释一下中间部分(以给出的图上的例子为例):

  • 左边节点遍历完成之后,此时的pRootOfTree就是最左边的叶子节点。链表是需要头指针的,把此时的pRootOfTree赋值给Head,node(代表的是当前指针)指向pRootOfTree。
  • 递归到了6身上,这是当前链表的指针是4,pRootOfTree指针是6,因此需要把4的右指针指向6,6的左指针指向4,node赋值为6。
  • 递归到了8,此时pRootOfTree是8,node是6,继续刚才的操作。
function Convert(pRootOfTree)
{
    let head=null;
    let node=null;
    function treeToNode(pRootOfTree){
        if(!pRootOfTree) return
        treeToNode(pRootOfTree.left)
        if(head==null){
            head=pRootOfTree;
            node=pRootOfTree;
        }else{
            node.right=pRootOfTree;
            pRootOfTree.left=node
            node=pRootOfTree;
        }
        treeToNode(pRootOfTree.right)
    }
    treeToNode(pRootOfTree)
    return head;
}

(继续下一个)

判断二叉树是不是平衡二叉树

描述:
输入一棵节点数为 n 二叉树,判断该二叉树是否是平衡二叉树。
在这里,我们只需要考虑其平衡性,不需要考虑其是不是排序二叉树
平衡二叉树(Balanced Binary Tree),具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
样例解释:
在这里插入图片描述
输入:
{1,2,3,4,5,6,7}
返回值:
true

解决这道题首先是要知道到底什么是平衡二叉树?
任意节点的子树的高度差都小于等于 1
针对这道题,还是要递归,后续遍历,得到左右树的高度,如果差值小于等于1,就取两者最大的加一。如果大于1就表示此时的树并不符合平衡二叉树。
注意这里返回的是树的高度,如果不符合就返回-1,一次每次递归的时候,都要判断返回值是否是-1。

function IsBalanced_Solution(pRoot)
{
    if(!pRoot) return true
    function stack(root){
        if(!root) return 0;
        var left=stack(root.left);
        if(left==-1) return -1
        var right=stack(root.right);
        if(right==-1 || Math.abs(left-right)>1) return -1
        return Math.max(left,right)+1
    }
    if(stack(pRoot)!==-1) return true;
    else false;
}

(继续下一个)

二叉树的下一个节点

描述
给定一个二叉树其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的next指针。下图为一棵有9个节点的二叉树。树中从父节点指向子节点的指针用实线表示,从子节点指向父节点的用虚线表示.
示例:
输入:{8,6,10,5,7,9,11},8
返回:9
解析:这个组装传入的子树根节点,其实就是整颗树,中序遍历{5,6,7,8,9,10,11},根节点8的下一个节点就是9,应该返回{9,10,11},后台只打印子树的下一个节点,所以只会打印9,如下图,其实都有指向左右孩子的指针,还有指向父节点的指针,下图没有画出来
在这里插入图片描述
输入描述:
输入分为2段,第一段是整体的二叉树,第二段是给定二叉树节点的值,后台会将这2个参数组装为一个二叉树局部的子树传入到函数GetNext里面,用户得到的输入只有一个子树根节点
返回值描述:
返回传入的子树根节点的下一个节点,后台会打印输出这个节点
输入:
{8,6,10,5,7,9,11},8
返回值:
9

解题思路:

function zhongxu(node){
    while(node.left){
        node=node.left;
    }
    return node;
}
function GetNext(pNode)
{
    //下一个节点应该是该节点右子树中序遍历的第一个。或者是父亲的父亲
    if(pNode.right){
        return zhongxu(pNode.right);
    }else{
        let parent=pNode.next;
        if(!parent){
            return null;
        }
        if(parent.left==pNode){
            return parent;
        }else{
            while(parent.next!=null&&parent.next.left!==parent){
                parent=parent.next;
            }
            return parent.next;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值