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

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

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

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

示例 1:

输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出: 3
解释: 节点 5 和节点 1 的最近公共祖先是节点 3。
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出: 5
解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。

分析:

有三种情况,p,q 都在左子树或右子树,p,q分别在左子树和右子树。

用到了分治法的思想,若是对于一个树结点,在左子树中找到了A,在右子树中找到了B,那说明此结点是公共节点。

class Solution(object):
    def lowestCommonAncestor(self, root, p, q):
        if root is None: return None
        # root为p或者root为q,说明找到了p和q其中一个
        if (root is p) or (root is q): return root
        # 递归调用当前节点的左子树
        left = self.lowestCommonAncestor(root.left,p,q)
        # 递归调用当前节点的右子树
        right = self.lowestCommonAncestor(root.right,p,q)
        # 若左子树找到了p,右子树找到了q,说明此时的root就是公共祖先
        if left and right: return root
        # 若左子树是none,右子树不是,说明右子树找到了A或B
        if not left: return right
        # # 若右子树是none,左子树不是,说明左子树找到了A或B
        if not right:return left
        # 如果左边,右边都没找到呢?

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

参考:https://blog.csdn.net/wenqiwenqi123/article/details/79952043 


这道题根本不会(????)以下是非递归版本:(谁能想到呢?)

首先说明:这个ppt是错误的,所以以下我照这个思路写的代码就是错的。

比如说p=5,q=1。那么先序遍历的结果(图里这个树)是3 5 6 2 7 4 1 0 8。

这个思路的答案是最后一个相同节点,那么是5,但是答案是3!!!

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

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

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

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

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

非递归版本——代码:

class Solution(object):
    def lowestCommonAncestor(self, root, p, q):
        """
        :type root: TreeNode
        :type p: TreeNode
        :type q: TreeNode
        :rtype: TreeNode
        """

        p_path, p_result = [], []
        self.dfs(root, p, p_path, p_result)
        q_path, q_result = [], []
        self.dfs(root, q, q_path, q_result)

        # 求最短的那dfs个路径
        # print("p:",p_result)
        # print("q:",q_result)

        if len(p_result)<len(q_result):
            path_len = len(p_result)
        else:
            path_len = len(q_result)

        result = TreeNode(0)
        for i in range(path_len):
            if p_result[i].val == q_result[i].val:
                result = p_result[i]

        return result


    def dfs(self,node,search,path,result):
        # 先序遍历(深度优先遍历)
        # node:正在遍历的结点;search:希望遍历到的结点
        if node:
            # 当node为空或已找到search结点,finish=1为找到
            path.append(node)
            while path:
                node = path.pop()
                result.append(node)
                # print(result)
                if node.val == search.val:
                    return result
                if node.right:
                    path.append(node.right)
                if node.left:
                    path.append(node.left)
        return result

相关文章: