二叉树的最近公共祖先

二叉树的最近公共祖先

题目

给定一个二叉树的根节点 root 和两个节点pq,请找到这两个节点的最近公共祖先。最近公共祖先定义为:在二叉树中,pq 的最近公共祖先是一个节点,该节点是pq的最低祖先节点,即pq都是这个节点的子孙(子孙的定义包括自己)。

输入格式

  • 一个二叉树的根节点 root
  • 两个节点pq

输出格式

返回最近公共祖先节点

输入样例

root = [3, 5, 1, 6, 2, 0, 8, null, null, 7, 4]
p = 5
q = 1

二叉树的结构

        3
       / \
      5   1
     / \ / \
    6  2 0  8
      / \
     7   4

输出样例

3

解答

这道题目要求找到二又树中两个节点 pq。的最近公共祖先。最直接的思路是通过递归遍历树的方法来解决这个问题。我们可以采用“自底向上”的递归方式,检查每个节点,看看它是否是pq 的公共祖先。

核心思路如下:

  1. 如果当前结点为null,返回 null

  2. 如果当前结点是pq,那么它就是其中一个节点的祖先,返回当前结点。

  3. 递归检查当前结点的左右孩子,分别在左右子树中搜索pq

  4. 根据左右子树的搜索结果:

•如果左右子树同时返回非空,说明pq 分别位于当前结点的左右子树,当前结点即为最近公共祖先。

•如果只有一个子树返回非空,说明pq 都在那个子树(或者其中一个在子树,一个就是当前结点),返回该非空的子树节点。

java

// 定义二叉树节点
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

public class Solution {
    // 求二叉树根节点root中节点p和q的最近公共祖先
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        // 如果当前节点为空,或者当前节点是p或q,则返回当前节点
        // 这意味着我们找到了p、q其中之一,或者到达了树的末端
        if (root == null || root == p || root == q) {
            return root;
        }

        // 递归寻找p和q在左子树中的最近公共祖先
        TreeNode left = lowestCommonAncestor(root.left, p, q);
        // 递归寻找p和q在右子树中的最近公共祖先
        TreeNode right = lowestCommonAncestor(root.right, p, q);

        // 如果左子树和右子树都找到了p或q,说明当前节点root是最近公共祖先
        if (left != null && right != null) {
            return root;
        }

        // 如果只有左子树找到一个p或q,则返回左子树的结果(可能是p或q)
        // 如果只有右子树找到一个p或q,则返回右子树的结果(可能是p或q)
        return left != null ? left : right;
    }
}

python

# 定义二叉树节点类
class TreeNode:
    def __init__(self, x):
        self.val = x  # 节点的值
        self.left = None  # 左子树
        self.right = None  # 右子树

class Solution:
    # 求二叉树root中节点p和q的最近公共祖先
    def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:
        # 如果当前节点为空,或者当前节点是p或q,直接返回当前节点
        if not root or root == p or root == q:
            return root
        
        # 在左子树中递归寻找p和q的最近公共祖先
        left = self.lowestCommonAncestor(root.left, p, q)
        # 在右子树中递归寻找p和q的最近公共祖先
        right = self.lowestCommonAncestor(root.right, p, q)
        
        # 如果左子树和右子树都找到了p或q,说明当前节点root是最近公共祖先
        if left and right:
            return root
        
        # 如果只有左子树找到一个p或q,则返回左子树的结果(可能是p或q)
        # 如果只有右子树找到一个p或q,则返回右子树的结果(可能是p或q)
        return left if left else right

C++

// 定义二叉树节点结构体
struct TreeNode {
    int val;  // 节点的值
    TreeNode *left;  // 左子树
    TreeNode *right;  // 右子树
    
    // 构造函数
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

class Solution {
public:
    // 求二叉树root中节点p和q的最近公共祖先
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        // 如果当前节点为空,或者当前节点是p或q,直接返回当前节点
        // 这意味着我们找到了p、q其中之一,或者到达了树的末端
        if (root == nullptr || root == p || root == q) {
            return root;
        }
        
        // 在左子树中递归寻找p和q的最近公共祖先
        TreeNode* left = lowestCommonAncestor(root->left, p, q);
        // 在右子树中递归寻找p和q的最近公共祖先
        TreeNode* right = lowestCommonAncestor(root->right, p, q);
        
        // 如果左子树和右子树都找到了p或q,说明当前节点root是最近公共祖先
        if (left != nullptr && right != nullptr) {
            return root;
        }
        
        // 如果左子树找到一个p或q,则返回左子树的结果(可能是p或q)
        // 如果右子树找到一个p或q,则返回右子树的结果(可能是p或q)
        return left != nullptr ? left : right;
    }
};

你可能感兴趣的:(算法训练营,算法,数据结构)