二叉树基础题(五):二叉树的下一个节点&最低公共祖先节点


(尊重劳动成果,转载请注明出处:https://yangwenqiang.blog.csdn.net/article/details/105928523
冷血之心的博客)

这段时间完成了职业生涯第一次跳槽,对算法题目有了一个更深的认识和理解,这里将二叉树常见的面试题目以及解法补充完善。

二叉树基础题(一):先序遍历&中序遍历&后序遍历

二叉树基础题(二):分层遍历&二叉树深度&是否相同的树

二叉树基础题(三):完全二叉树的判断&平衡二叉树的判断

二叉树基础题(四):对称二叉树的判断&之字形分层遍历二叉树

二叉树基础题(五):二叉树的下一个节点&最低公共祖先节点

二叉树基础题(六):树的子结构&二叉搜索树的判断&镜像二叉树


在本篇博文中,我们介绍再来看两道二叉树相关的高频面试题目吧,如下所示:

  • 求二叉树中序遍历的下一个节点
  • 求二叉树中两个节点的最低公共祖先节点

题目一:求二叉树中序遍历的下一个节点

给定一棵二叉树和其中的一个结点,如何找出中序遍历顺序的下一个结点? 树中的结点除了有两个分别指向左右子结点的指针以外,还有一个指向父结点的指针(可以使用next表示)。

分析:

画图分析,找一个二叉树。然后我们必须了解何为中序遍历,这里就不展开介绍了。我们可以选择几个二叉树的节点,分析下一个节点有那些规律。总结之后,分情况讨论如下:

  • 若当前结点有右子树时,其下一个结点为右子树中最左子结点;
  • 若当前结点无右子树时:
    • 若当前结点为其父结点的左子结点时,其下一个结点为其父结点;
    • 若当前结点为其父结点的右子结点时,继续向上遍历父结点的父结点,直到找到一个结点是其父结点的左子结点(与(1)中判断相同),该结点即为下一结点。
主要是分为了三种情况,依次解决即可:
/*
public class TreeLinkNode {
    int val;
    TreeLinkNode left = null;
    TreeLinkNode right = null;
    TreeLinkNode next = null;

    TreeLinkNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {
    public TreeLinkNode GetNext(TreeLinkNode targetNode){
        if(targetNode==null)
            return null;
        TreeLinkNode cur = null;
        // 判断该节点是否有右孩子
        if(targetNode.right!=null){
            cur = targetNode.right;
            while(cur.left!=null){  // 找出其右孩子节点的 最 左边孩子节点
                cur = cur.left;
            }
            return cur;
        }
        
        // 若该节点没有右孩子节点,则判断其是否是其父节点的左孩子
        if(targetNode.next==null){
            return null;
        }
        if(targetNode==targetNode.next.left){
            return targetNode.next;
        }
        
        // 此时,该节点既没有右孩子节点,也不是其父节点的左孩子
        // 步骤:向上寻找其父节点,直到找到父节点是其父节点的左孩子为此,此时,下一个节点为最后那个父节点
        while(targetNode.next!=null){
            if(targetNode==targetNode.next.left){
                return targetNode.next;
            }
            // 继续寻找
            targetNode = targetNode.next;
        }
        
        return null;
    }
}
总结:

这个题目说白了,首先需要了解何为中序遍历(这个都不知道,那你别去面试了)。然后需要使用特例法,化抽象为具体,通过对二叉树节点之间的关系进行分析,找到需要处理的三种情况,从而得到解决问题的思路。总之,算法有难度,但是思路还算比较清晰。

题目二:最低公共祖先节点

在一颗二叉树中,求出给定两个节点的最低公共祖先节点!

讨论:如果当前的二叉树是一颗二叉搜索树?

这还有啥好说的,我们找到一个节点,位于两个节点的value值中间即可!代码实现如下:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root==null||root==p||root==q)
            return root;
        if(root.val>p.val&&root.val>q.val)
            return lowestCommonAncestor(root.left,p,q);
        if(root.val<p.val&&root.val<q.val)
            return lowestCommonAncestor(root.right,p,q);
        else
            return root;
    }
}

but, however,如果这是一颗普通的二叉树的?如下所示:
在这里插入图片描述
这个时候,需要我们递归的去左右子树上寻找目标节点,(详见代码注释)代码实现如下:

public static BTreeNode getLastCommonNode(BTreeNode pRoot, BTreeNode pLeft, BTreeNode pRight){
	//发现目标节点则通过返回值标记该子树发现了某个目标结点
	if(pRoot == null || pRoot == pLeft || pRoot == pRight){
		return pRoot;
	}
	//查看左子树中是否有目标结点,没有为null
	BTreeNode left = getLastCommonNode(pRoot.left, pLeft, pRight);
	//查看右子树是否有目标节点,没有为null
	BTreeNode right = getLastCommonNode(pRoot.right, pLeft, pRight);
	//都不为空,说明做右子树都有目标结点,则公共祖先就是本身
	if(left != null && right != null){
		return pRoot;
	}
	//如果发现了目标节点,则继续向上标记为该目标节点
	return left == null ? right : left;
}

总结:

二叉树的下一个节点因为代码量相对较大,考察时候需要更多的时间。所以,在面试中出现的概率相对比较低吧(当然也不排除想头条那种面试时长可达两个小时的,那就随意了)。最低公共祖先节点则是一道各个公司都喜欢考察的二叉树基础题目,校招时候更容易遇到哦~

后续我会继续更新二叉树相关基础题目,感兴趣的同学可以持续关注交流~


注意啦,注意啦~

欢迎大家关注我的牛客专栏《Java开发岗面试题全解析》 ,点击图片查看详情。

Java开发岗高频面试题全解析,专栏共计32节,已经全部更新完毕。

专栏分9个模块来对Java岗位面试中的知识点进行解析,包括通用面试技能,Java基础,Java进阶,网络协议,常见框架以及算法,设计模式等。

专栏串点成面的解析每个面试题背后的技术原理,由浅入深,循序渐进,力争让大家掌握面试题目的背后的技术原理,摒弃背题模式的陋习。


如果对你有帮助,记得点赞哈,欢迎大家关注我的博客,关注公众号(文强的技术小屋),学习更多技术知识,一起遨游知识海洋~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

温柔狠角色

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值