二叉树:公共祖先问题

236. 二叉树的最近公共祖先

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点 5 和节点 1 的最近公共祖先是节点 3 。

思路

后序遍历就是天然的回溯过程,最先处理的一定是叶子节点。

如果找到一个节点,发现左子树出现结点p,右子树出现节点q,或者左子树出现结点q,右子树出现节点p,那么该节点就是节点p和q的最近公共祖先。

递归三部曲

1.确定递归函数返回值以及参数
找节点q或者p,返回最近公共节点。

2.确定终止条件
如果找到了节点p或者q,或者遇到空节点,就返回。

因为回溯的过程需要递归函数的返回值做判断,但本题我们依然要遍历树的所有节点。
搜索一条边的写法:

if (递归函数(root->left)) return ;

if (递归函数(root->right)) return ;

搜索整个树写法:

left = 递归函数(root->left);
right = 递归函数(root->right);
left与right的逻辑处理;

在递归函数有返回值的情况下:如果要搜索一条边,递归函数返回值不为空的时候,立刻返回,如果搜索整个树,直接用一个变量left、right接住返回值,这个left、right后序还有逻辑处理的需要,也就是后序遍历中处理中间节点的逻辑(也是回溯)。

3.确定单层递归的逻辑
如果left和right都不为空,说明此时root就是最近公共节点。
如果left为空,right不为空,就返回right,说明目标节点是通过right返回的,反之依然。
如果left和right都为空,返回空。

代码

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

        TreeNode left = lowestCommonAncestor(root.left,p,q);
        TreeNode right = lowestCommonAncestor(root.right,p,q);

        if(left != null && right != null){
            return root;
        }
        if(left == null && right != null){
            return right;
        }else if(left != null && right == null){
            return left;
        }else {
            return null;
        }
    }
}
posted @ 2021-05-08 11:03  当康  阅读(411)  评论(0编辑  收藏  举报