68 - II. 二叉树的最近公共祖先

题目:给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。https://leetcode-cn.com/problems/er-cha-shu-de-zui-jin-gong-gong-zu-xian-lcof/submissions/

写在前面:这一题不同于68-I 二叉搜索树的最近公共祖先https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-zui-jin-gong-gong-zu-xian-lcof/(二叉搜索树具有左节点<父节点<右节点的性质),那一题的解决思路以及代码如下:

# 解题思路 如果要查找的两个节点1.任一个等于根结点值,或者这两个节点指分别位于根节点值的两侧,则返回根节点。2.如果这两个节点只在根节点值的左侧,在左子树查找,3.否则在右子树查找。
# 注意返回的是节点而非节点的值
class Solution:
    def lowestCommonAncestor(self, root: ‘TreeNode‘, p: ‘TreeNode‘, q: ‘TreeNode‘) -> ‘TreeNode‘:
        if p.val>q.val:
            p,q = q,p
        if p==root or q == root:
            return root
        if p.val<root.val and q.val> root.val:
            return root
        if p.val<root.val and q.val<root.val:
            return self.lowestCommonAncestor(root.left,p,q)
        if p.val>root.val and q.val>root.val:
            return self.lowestCommonAncestor(root.right,p,q)

针对本题:

方法一.保存路径形式的思考方式:

第一种:假设给我们的树中的节点包含一个指向父节点的指针

如果有了父节点的指针,到达4的逆序路径能得出来为4->2->5->3,到达6的逆序路径为6->5->3由于都有父节点指针,所以这个问题就转换成了求两个链表的第一个公共节点问题;

第二种:使用数组存储路径

我们可以使用两个数组保存路径,用先序遍历存储正向路径,如节点4的正向路径为3->5->2->4,节点6的正向路径为3->5->6,从头找到第一个不相同节点的前一个节点即可,这个例子就是指的节点5;

第二种思路的代码:

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def lowestCommonAncestor(self, root, p, q):
        """
        :type root: TreeNode
        :type p: TreeNode
        :type q: TreeNode
        :rtype: TreeNode
        """
        stack_1 = []
        stack_2 = []
        def dfs(root, node, stack):
            if not root:
                return False
            stack.append(root)
            if root.val == node.val:
                return True
            if (dfs(root.left, node, stack) or dfs(root.right, node, stack)):
                return True
            stack.pop()

        dfs(root, p, stack_1)
        dfs(root, q, stack_2)
        i = 0
        while i < len(stack_1) and i<len(stack_2) and stack_1[i] == stack_2[i]:
            result = stack_1[i]
            i += 1
        return result

方法二.递归

【思路】

因为lowestCommonAncestor(root, p, q)的功能是找出以root为根节点的两个节点p和q的最近公共祖先,所以递归体分三种情况讨论:

1.如果p和q分别是root的左右节点,那么root就是我们要找的最近公共祖先;

2.如果p和q都是root的左节点,那么返回lowestCommonAncestor(root.left,p,q);

3.如果p和q都是root的右节点,那么返回lowestCommonAncestor(root.right,p,q);

边界条件讨论:

1.如果root是null,则说明我们已经找到最底了,返回null表示没找到;

2.如果root与p相等或者与q相等,则返回root;

3.如果左子树没找到,递归函数返回null,证明p和q同在root的右侧,那么最终的公共祖先就是右子树找到的结点;

4.如果右子树没找到,递归函数返回null,证明p和q同在root的左侧,那么最终的公共祖先就是左子树找到的结点;

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def lowestCommonAncestor(self, root, p, q):
        """
        :type root: TreeNode
        :type p: TreeNode
        :type q: TreeNode
        :rtype: TreeNode
        """
        if not root or root == p or root == q:
            return root
        left = self.lowestCommonAncestor(root.left, p, q)
        right = self.lowestCommonAncestor(root.right, p, q)

        if not left:
            return right
        if not right:
            return left
        return root

原文地址:https://www.cnblogs.com/USTC-ZCC/p/12547620.html

时间: 2024-10-10 20:47:44

68 - II. 二叉树的最近公共祖先的相关文章

编程算法 - 二叉树的最低公共祖先 代码(C)

二叉树的最低公共祖先 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 二叉树的最低公共祖先(lowest common ancestor), 首先先序遍历找到两个结点的路径, 然后依据链表路径找到最低的公共祖先. 代码: /* * main.cpp * * Created on: 2014.6.12 * Author: Spike */ /*eclipse cdt, gcc 4.8.1*/ #include <iostream> #include

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

二叉树的最近公共祖先 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:"对于有根树 T 的两个结点 p.q,最近公共祖先表示为一个结点 x,满足 x 是 p.q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)." 例如,给定如下二叉树:  root = [3,5,1,6,2,0,8,null,null,7,4] 示例 1: 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1

奇安信集团笔试题:二叉树的最近公共祖先(leetcode236),杀死进程(leetcode582)

1. 二叉树最近公共祖先 奇安信集团 2020校招 服务端开发-应用开发方向在线考试 编程题|20分2/2 寻祖问宗 时间限制:C/C++语言 1000MS:其他语言 3000MS 内存限制:C/C++语言 65536KB:其他语言 589824KB 题目描述: 姓氏是人的符号标志,是家族血脉的传承:族谱是家族血脉传承的文字记载.同姓的两个中国人,根据族谱或许能够查出上面几代内是同一个祖先.查一下族谱,也许当代某位同姓名人就是你的远房亲戚,惊喜不惊喜,意外不意外!!! 输入 二元查找树(1.若左

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

* @lc app=leetcode.cn id=236 lang=cpp * * [236] 二叉树的最近公共祖先 * * https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/description/ * * algorithms * Medium (58.46%) * Likes:    300 * Dislikes: 0 * Total Accepted:    33.9K * Total Sub

【LeetCode】二叉树的最近公共祖先(2)

(一)二叉搜索树的最近公共祖先 题目(Easy):235. 二叉搜索树的最近公共祖先 题目描述: 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:"对于有根树 T 的两个结点 p.q,最近公共祖先表示为一个结点 x,满足 x 是 p.q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)." 例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5] 示例 1: 输入: root = [6

【剑指offer】【树】68-II.二叉树的最近公共祖先

二叉树的最近公共祖先 /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: TreeNode* lowestCommonAncestor(TreeNode* r

求二叉树的最低公共祖先

这个题目来讲,应该是在二叉树里面较为容易的题目了.那么如何下手呢?其实对于这样一棵二叉树来讲. 我们如何求它们的最低公共父节点呢? 假如是要你求5.6的公共父节点,那么是3.啰 为什么是3? 因为3的左子树是5,而右子树是6啰. 那么7.8的最低公共祖先呢? 1啊,因为1的左子树中有7.而1的右子树中有8啊. 那么思路来了.我们只要证明某一节点的左子树和右子树分别包含这两个节点就行了. 于是思路来了. 源代码: 注意:在本题中为了方便 ,我们传入的两个节点的值,而不是两个节的地址,呵呵,为了方便

二叉树的最小公共祖先问题

今天做了两个二叉树的题目, 挺简单的, 不用调试, 直接在提交框上敲完提交, 直接就通过了. 第一个题目是求二叉查找树的公共祖先, 因为是排序的, 所以很好做. 具体思路如下: 1 如果两个节点都比当前节点小, 那公共祖先必然是当前节点的左子树上, 所以递归左子树; 2 如果两个节点都比当前节点大, 那么同上, 递归右子树; 3 如果两个节点有一个为当前节点, 则当前节点为公共节点; 如果两个节点分别比当前节点小和大, 那么当前节点必为公共节点. 具体代码如下: class Solution {

满二叉树的最近公共祖先

满二叉树节点父子之间的关系. //题目描述 // //有一棵无穷大的满二叉树,其结点按根结点一层一层地从左往右依次编号,根结点编号为1.现在有两个结点a,b. //请设计一个算法,求出a和b点的最近公共祖先的编号. //给定两个int a, b.为给定结点的编号.请返回a和b的最近公共祖先的编号.注意这里结点本身也可认为是其祖先. //测试样例: //2,3 //返回:1 //思路:满二叉树的子节点与父节点之间的关系为root = child / 2 //利用这个关系,如果a != b,就让其中