vlambda博客
学习文章列表

一文解决二叉树的公共祖先的相关问题

    首先明确一个概念:什么是公共祖先?百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。

例如,给定如下二叉树:  root = [3,5,1,6,2,0,8,null,null,7,4]

    

    若根据以上的定义,若root是p,q的公共祖先,只可能是以下3种情况:

  • p和q分别在root的左子树和右子树中

  • p == root ,p在q的左子树或右子树中

  • q == root ,q在p的左子树或右子树中




    所以可以考虑使用递归,二叉树的问题使用递归的方式基本都可以解决,递归的出口为:

如果root == null || root == p || root == q

则直接返回root,否则接着递归root的左子树和右子树并返回,如果递归的左子树和右子树的结果都为空则仍返回root

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { if(root == null || root == p || root == q) return root; TreeNode left = lowestCommonAncestor(root.left, p, q); TreeNode right = lowestCommonAncestor(root.right, p, q); if(left == null) return right; if(right == null) return left; return root; }

    扩展:二叉搜索树的最近公共祖先

    作为二叉搜索树的祖先问题就相对简单一点,直接迭代就可以,无需使用递归的方式即可

    循环搜索:basecase:当节点为null时跳出;

  • 当p,q都在root的右子树中,直接继续向右子树遍历root = root.right

  • 当p,q都在root的右子树中,直接继续向右子树遍历root = root.right

  • 当p,q在root的两侧时,直接返回root


public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { while(root != null) { if(root.val < p.val && root.val < q.val) // p,q 都在 root 的右子树中 root = root.right; // 遍历至右子节点 else if(root.val > p.val && root.val > q.val) // p,q 都在 root 的左子树中 root = root.left; // 遍历至左子节点 else break; } return root; }