Leetcode--------二叉树Part2

226. 翻转二叉树

翻转一棵二叉树。

示例:

输入:

     4
   /   \
  2     7
 / \   / \
1   3 6   9

输出:

     4
   /   \
  7     2
 / \   / \
9   6 3   1

代码:

class Solution:
    def invertTree(self, root: TreeNode) -> TreeNode:
        """
        采用递归的方法
        """
        #一:确定递归的参数和返回值
        def digui(root: TreeNode):
            if root == None:
                #二:确定递归停止的条件
                return root
            #开始交换左右节点
            temp = root.left
            root.left = root.right
            root.right = temp
            #三:确定单层递归的逻辑
            digui(root.left)
            digui(root.right)
        
        digui(root)
        return root

101. 对称二叉树

给定一个二叉树,检查它是否是镜像对称的。

例如,二叉树 [1,2,2,3,4,4,3] 是对称的。

    1
   / \
  2   2
 / \ / \
3  4 4  3

但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:

    1
   / \
  2   2
   \   \
   3    3

代码:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isSymmetric(self, root: TreeNode) -> bool:
        """
        思路一:直接翻转根节点左右子树--后面比较的时候比较麻烦,2个地址比较不对--放弃
        """
        # left_tree = root.left
        # right_tree = root.right
        # """
        # 翻转二叉树,用递归
        # """
        # def invertTree(root: TreeNode):
        #     if root == None:
        #         return root
        #     temp = root.left
        #     root.left = root.right
        #     root.right = temp
        #     invertTree(root.left)
        #     invertTree(root.right)
        # invertTree(right_tree)
        # print("left_tree",left_tree)
        # print("right_tree",right_tree)
        # if left_tree == right_tree:
        #     return True
        # else:
        #     return False
        """
        思路二:直接比较根节点的左右子树,本题遍历只能是“后序遍历”,因为我们要通过
        递归函数的返回值来判断两个子树的内侧节点和外侧节点是否相等。正是因为要遍历两
        棵树而且要比较内侧和外侧节点,所以准确的来说是一个树的遍历顺序是左右中,一个树
        的遍历顺序是右左中。
        """
        #1.确定递归函数的参数和返回值
        def compare(left_root: TreeNode,right_root: TreeNode):
            #2.确定终止条件----要比较两个节点数值相不相同,首先要把两个节点为空的情况弄清楚
            """
            左节点为空,右节点不为空,不对称,return false
            左不为空,右为空,不对称 return false
            左右都为空,对称,返回true
            """
            if left_root == None and right_root != None:
                return False
            if left_root != None and right_root == None:
                return False
            if left_root == None and right_root == None:
                return True
            if left_root.val != right_root.val:
                return False
            #下面不能else-------------后面继续研究
            #不能直接就返回True了
            # else:
            #     return True
            """
            此时已经排除掉了节点为空的情况,那么剩下的就是左右节点不为空:
            左右都不为空,比较节点数值,不相同就return false
            此时左右节点不为空,且数值也不相同的情况我们也处理了。
            """
            #3.确定单层递归的逻辑
            """
            比较二叉树外侧是否对称:传入的是左节点的左孩子,右节点的右孩子。
            比较内测是否对称,传入左节点的右孩子,右节点的左孩子。
            如果左右都对称就返回true ,有一侧不对称就返回false 。
            """
            outside = compare(left_root.left,right_root.right)
            inside  = compare(left_root.right,right_root.left)
            isSame = outside and inside
            return isSame
        
        if root == None:
            return True
        return compare(root.left,root.right) 
        

104. 二叉树的最大深度

给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明: 叶子节点是指没有子节点的节点。

示例:
给定二叉树 [3,9,20,null,null,15,7]

    3
   / \
  9  20
    /  \
   15   7

返回它的最大深度 3 。

代码:

class Solution:
    def maxDepth(self, root: TreeNode) -> int:
        """
        和层次遍历很相关
        """
        if root == None:
            return 0
        queue = [root]
        out_list = []
        while len(queue) > 0:
            inner_list = []
            lens = len(queue)
            for _ in range(lens):
                #遍历当前节点值
                cur_node = queue.pop(0)
                inner_list.append(cur_node.val)
                #左右子节点都入队
                if cur_node.left != None:
                    queue.append(cur_node.left)
                if cur_node.right != None:
                    queue.append(cur_node.right)
            out_list.append(inner_list)
        return len(out_list)

559. N 叉树的最大深度

给定一个 N 叉树,找到其最大深度。

最大深度是指从根节点到最远叶子节点的最长路径上的节点总数。

N 叉树输入按层序遍历序列化表示,每组子节点由空值分隔(请参见示例)。

示例 1:

输入:root = [1,null,3,2,4,null,5,6]
输出:3

代码:

class Solution:
    def maxDepth(self, root: 'Node') -> int:
        """
        和层次遍历很相关----对于多叉树,就是将一个节点的
        所有孩子节点都入队
        """
        if root == None:
            return 0
        queue = [root]
        out_list = []
        while len(queue) > 0:
            inner_list = []
            lens = len(queue)
            for _ in range(lens):
                #遍历当前节点值
                cur_node = queue.pop(0)
                inner_list.append(cur_node.val)
                #所有孩子节点都入队
                for chil in cur_node.children:
                    queue.append(chil)
            out_list.append(inner_list)
        return len(out_list)

111. 二叉树的最小深度

给定一个二叉树,找出其最小深度。

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

说明:叶子节点是指没有子节点的节点。

示例 1:

输入:root = [3,9,20,null,null,15,7]
输出:2

代码:

class Solution:
    def minDepth(self, root: TreeNode) -> int:
        """
        找到根节点的最小高度
        """
        #1.确定递归函数的参数和返回值
        def getDepth(root: TreeNode):
            #2.确定终止条件---终止条件也是遇到空节点返回0,表示当前节点的高度为0。
            if root == None:
                return 0
            #3.确定单层递归的逻辑
            leftDepth = getDepth(root.left)
            rightDepth = getDepth(root.right)            
            """
            注意:这种写法错误,假如根节点左子树为空,那么最小深度就成1啦,这是错误的
            如果左子树为空,右子树不为空,说明最小深度是 1 + 右子树的深度。
            反之,右子树为空,左子树不为空,最小深度是 1 + 左子树的深度。
            最后如果左右子树都不为空,返回左右子树深度最小值 + 1 。
            """
            #这里要考虑所有情况,不然就会空指针
            if root.left == None and root.right != None:
                return (1 + rightDepth)
            if root.left != None and root.right == None:
                return (1 + leftDepth)
            if root.left == None and root.right == None:
                return 1
            if root.left != None and root.right != None:
                return  min(leftDepth,rightDepth)+1
            
        return getDepth(root)

222. 完全二叉树的节点个数

给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。

完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。

示例 1:

输入:root = [1,2,3,4,5,6]
输出:6

代码:

class Solution:
    def countNodes(self, root: TreeNode) -> int:
        """
        还是采用递归,节点的个数===左节点的个数+右节点的个数+1
        """
        #1.传入根节点
        def get_nodes(root: TreeNode):
            #2.终止条件
            if root == None:
                return 0
            #3.代码逻辑
            left_nodes = get_nodes(root.left)
            right_nodes = get_nodes(root.right)
            
            if root.left != None and root.right == None:
                return 2
            if root.left == None and root.right == None:
                return 1
            if root.left != None and root.right != None:
                return 1+left_nodes+right_nodes
        
        return get_nodes(root)

110. 平衡二叉树

给定一个二叉树,判断它是否是高度平衡的二叉树。

本题中,一棵高度平衡二叉树定义为:

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。

示例 1:

输入:root = [3,9,20,null,null,15,7]
输出:true

代码:

class Solution:
    def isBalanced(self, root: TreeNode) -> bool:
        """
        同样采用递归来做,判断左右节点的深度差
        求二叉树深度可以从上到下去查 所以需要前序遍历(中左右),
        而二叉树高度只能从下到上去查,所以只能后序遍历(左右中)
        """
        """
        此时大家应该明白了既然要求比较高度,必然是要后序遍历。

        递归三步曲分析:

        1. 明确递归函数的参数和返回值
        参数的话为传入的节点指针,就没有其他参数需要传递了,返回值要返回传入节点为根节点树的深度。

        那么如何标记左右子树是否差值大于1呢。

        如果当前传入节点为根节点的二叉树已经不是二叉平衡树了,还返回高度的话就没有意义了。

        所以如果已经不是二叉平衡树了,可以返回-1 来标记已经不符合平衡树的规则了。
        2. 明确终止条件
        递归的过程中依然是遇到空节点了为终止,返回0,表示当前节点为根节点的树高度为0
        3. 明确单层递归的逻辑
        如何判断当前传入节点为根节点的二叉树是否是平衡二叉树呢,当然是左子树高度和右子树高度相差。

        分别求出左右子树的高度,然后如果差值小于等于1,则返回当前二叉树的高度,否则则返回-1,表示已经不是二叉树了。
        
        """
        def Get_Deeps(root: TreeNode):
            if root == None:
                return 0
            left_deep = Get_Deeps(root.left)#左
            if left_deep == -1:
                return -1
            right_deep = Get_Deeps(root.right)#右
            if right_deep == -1:
                return -1
            
            if left_deep != None and right_deep != -1:
                sub_deep = abs(left_deep - right_deep)
                if sub_deep > 1:
                    return -1
                else:
                    #这里别忘了加1
                    return 1+max(left_deep,right_deep)
        if Get_Deeps(root) == -1:
            return False
        else:
            return True

257. 二叉树的所有路径

给定一个二叉树,返回所有从根节点到叶子节点的路径。

说明: 叶子节点是指没有子节点的节点。

示例:

输入:

   1
 /   \
2     3
 \
  5

输出: ["1->2->5", "1->3"]

解释: 所有根节点到叶子节点的路径为: 1->2->5, 1->3

代码:

class Solution:
    def binaryTreePaths(self, root: TreeNode) -> List[str]:
        """
        还是使用递归
        因为要寻找从根节点到叶子节点的路径,所有应该使用前序遍历,即先根节点的顺序
        """
        """
        1.定义函数返回值和参数
        参数:当前节点、应该记录走过的路径集合
        返回值:不需要
        """
        def get_paths(root: TreeNode,now_paths:list,all_paths:list):
            """
            2.终止条件
            即结束逻辑后要做的处理,这里只要判断当前节点是叶节点
            就return,不用到空节点
            """
            if root.left == None and root.right == None:
                #当前节点是叶子节点
                now_paths.append(str(root.val))
                all_paths.append(now_paths.copy())
                return 
            """
            3.逻辑语句:前序遍历
            """
            #直接加入到路径中
            now_paths.append(str(root.val))
            #上面没有处理当前为None的逻辑,在这里处理
            if root.left != None:
                """
                回溯和递归是一一对应的,有一个递归,就要有一个回溯
                """
                get_paths(root.left,now_paths,all_paths)
                #退回上一步
                now_paths.pop(-1)
            if root.right != None:
                get_paths(root.right,now_paths,all_paths)
                now_paths.pop(-1)         
        now_paths = list()
        all_paths = list()
        get_paths(root,now_paths,all_paths)
        """
        将路径封装成要求的形式
        """  
        res = list(map(lambda x:"->".join(x),all_paths))
        return res

 100. 相同的树

给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

示例 1:

输入:p = [1,2,3], q = [1,2,3]
输出:true

 代码:

class Solution:
    def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
        """
        同样使用递归
        """
        def if_same(p: TreeNode, q: TreeNode):
            #停止条件
            if p == None and q != None:
                return False
            if p != None and q == None:
                return False
            if p == None and q == None:
                #这里直接返回True了,没有调用,因为都是空节点了
                #就不会再有子节点,也就不用再去判断了
                return True 
            
            #遍历当前节点,且都不为空
            #若不相等,直接返回False
            if p.val != q.val:
                return False
            #若相等,还要看其子节点是否相等,后面就去递归
            left_ifsame = if_same(p.left, q.left)
            right_ifsame = if_same(p.right, q.right)
            if left_ifsame and right_ifsame:
                return True
            else:
                return False
            
        return if_same(p, q)

404. 左叶子之和

计算给定二叉树的所有左叶子之和。

示例:

    3
   / \
  9  20
    /  \
   15   7

在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24

代码:

class Solution:
    def sumOfLeftLeaves(self, root: TreeNode) -> int:
        """
        递归法:找到节点的左节点不为空,且该左节点的左右子节点都为空,
        递归方法:知道左节点的左叶子之和、知道右节点的左叶子之和
        最后才能知道以当前树的的所有左叶子之和。即根节点的所有左叶子之和
        故:用后序遍历比较好
        """
        def left_leaf_sum(root: TreeNode):
            #2.0判断截止条件:
            #找到节点的左节点不为空,且该左节点的左右子节点都为空,便停止
            if root == None:
                return 0
            #3.0代码逻辑
            """
            ---------->对当前节点root而言,要处理的逻辑
            """
            """
            这表示以当前节点的左子节点为根节点这棵树上所有左叶子之和
            """
            left_leaf_leftS = left_leaf_sum(root.left)
            """
            这表示以当前节点的右子节点为根节点这棵树上所有左叶子之和
            """
            left_leaf_rightS = left_leaf_sum(root.right)
            """
            在计算当前root节点的左右子节点是否含有左叶子节点
            """
            now_nums = 0
            if root.left != None and root.left.left == None and root.left.right == None:
                now_nums = root.left.val
            
            """
            当前root节点含有的总左叶子之和
            """
            return left_leaf_leftS + left_leaf_rightS + now_nums
        
        return left_leaf_sum(root)

513. 找树左下角的值

给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。

假设二叉树中至少有一个节点。

示例 1:

输入: root = [2,1,3]
输出: 1

示例 2:

 输入: [1,2,3,4,null,5,6,null,null,7] 输出: 7

 代码:

class Solution:
    def findBottomLeftValue(self, root: TreeNode) -> int:
        """
        方法一:用分层遍历的代码
        """
#         if root == None:
#             return []
#         #把根节点放入队列中
#         queue = [root]
#         out_list = []
#         while len(queue) > 0:
#             #len = 1
#             length = len(queue)
#             in_list = []
#             for _ in range(length):
#                 #取出根节点
#                 cur_node = queue.pop(0)
#                 in_list.append(cur_node.val)
#                 #若左子节点不为空
#                 if cur_node.left != None:
#                     queue.append(cur_node.left)
#                 if cur_node.right != None:
#                     queue.append(cur_node.right)
#             out_list.append(in_list)
                
#         return out_list[-1][0]
        """
        方法二:用遍历的方法
        找到树最深的那一层,且最左侧的那个节点,(用前序遍历)
        还要用到回溯
        """
        maxLen = 1
        maxleftValue = root.val
        def traversal(root: TreeNode,leftLen: int):
            """
            nonlocal关键字用来在函数或其他作用域中使用外层(非全局)变量
            """
            nonlocal maxLen, maxleftValue
            #找到该节点了,看是否是叶节点
            if root.left == None and root.right == None:
                #中
                if leftLen > maxLen:
                    maxLen = leftLen
                    maxleftValue = root.val
            #左
            if root.left != None:
                leftLen += 1
                traversal(root.left,leftLen)
                #当该节点的子节点遍历结束-----回溯
                leftLen -= 1
            #右
            if root.right != None:
                leftLen += 1
                traversal(root.right,leftLen)
                #当该节点的子节点遍历结束-----回溯
                leftLen -= 1
            
        traversal(root,1) 
        return maxleftValue

112. 路径总和

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum ,判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。

叶子节点 是指没有子节点的节点。

示例 1:

 输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22 输出:true

 代码:

class Solution:
    def hasPathSum(self, root: TreeNode, targetSum: int) -> bool:
        """
        采用递归
        """
        def path_sums(root: TreeNode, targetSum: int):
            #代码终止条件
            if root.left == None and root.right == None and targetSum == 0:
                return True
            if root.left == None and root.right == None and targetSum != 0:
                return False
            #左
            if root.left != None:
                targetSum -= root.left.val
                #假如左子树已经符合条件,直接返回True
                if path_sums(root.left,targetSum):
                    return True
                #回溯
                targetSum += root.left.val
            
            #右
            if root.right != None:
                targetSum -= root.right.val
                if path_sums(root.right,targetSum):
                    return True
                #回溯
                targetSum += root.right.val
            #中
            #上面都没return ,说明没找到
            return False
            
        if root == None:
            return False
        return path_sums(root, targetSum-root.val)

617. 合并二叉树

给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠。

你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。

示例 1:

输入: 
	Tree 1                     Tree 2                  
          1                         2                             
         / \                       / \                            
        3   2                     1   3                        
       /                           \   \                      
      5                             4   7                  
输出: 
合并后的树:
	     3
	    / \
	   4   5
	  / \   \ 
	 5   4   7

注意: 合并必须从两个树的根节点开始。

 代码:

class Solution:
    def mergeTrees(self, root1: TreeNode, root2: TreeNode) -> TreeNode:
        #1.0参数、返回值
        def mergeTrees(root1: TreeNode, root2: TreeNode) -> TreeNode:
            #2.0终止条件
            if root1 == None:
                return root2
            if root2 == None:
                return root1
            #3.0业务逻辑
            #这是当前节点的新合并后的左子树
            root_left = mergeTrees(root1.left,root2.left)
            #这是当前节点的新合并后的右子树
            root_right = mergeTrees(root1.right,root2.right)
            
            root_val = (root1.val+root2.val)
            root1.val = root_val
            #当前节点的新左子节点是合并后的root_left
            root1.left = root_left
            #当前节点的新右子节点是合并后的root_left
            root1.right = root_right
            return root1
        
        return mergeTrees(root1,root2)

700. 二叉搜索树中的搜索

给定二叉搜索树(BST)的根节点和一个值。 你需要在BST中找到节点值等于给定值的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 NULL。

例如,

给定二叉搜索树:

        4
       / \
      2   7
     / \
    1   3

和值: 2

你应该返回如下子树:

      2     
     / \   
    1   3

代码:

class Solution:
    def searchBST(self, root: TreeNode, val: int) -> TreeNode:
        # 方法一:使用二叉树的方法
        def traversal(root: TreeNode):
            if root == None:
                return
            if root.val == val:
                return root
            left_node = traversal(root.left)
            right_node = traversal(root.right)
            if left_node != None:
                return left_node
            if right_node != None:
                return right_node
            
        return traversal(root)
        #方法二:使用二叉搜索树的方法
        def traversal(root: TreeNode):
            if root == None:
                return 
            if root.val == val:
                return root
            if root.val > val:
                #去左子树去找
                return traversal(root.left)
            if root.val <= val:
                #去右子树去找
                return traversal(root.right)
        
        return traversal(root)

 98. 验证二叉搜索树

给定一个二叉树,判断其是否是一个有效的二叉搜索树。

假设一个二叉搜索树具有如下特征:

  • 节点的左子树只包含小于当前节点的数。
  • 节点的右子树只包含大于当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。

示例 1:

输入:
    2
   / \
  1   3
输出: true

代码:

class Solution:
    def isValidBST(self, root: TreeNode) -> bool:
        """
        要知道中序遍历下,输出的二叉搜索树节点的数值是有序序列
        """
        res = []
        def traversal(root: TreeNode):
            if root == None:
                return
            traversal(root.left)
            res.append(root.val)
            traversal(root.right)
        traversal(root)
        #判断一个列表是否是有序的
        for i in range(len(res)-1):
            if res[i] >= res[i+1]:
                return False
        return True

530. 二叉搜索树的最小绝对差

给你一棵所有节点为非负值的二叉搜索树,请你计算树中任意两节点的差的绝对值的最小值。

示例:

输入:

   1
    \
     3
    /
   2

输出:
1

解释:
最小绝对差为 1,其中 2 和 1 的差的绝对值为 1(或者 2 和 3)。

 代码:

class Solution:
    def getMinimumDifference(self, root: TreeNode) -> int:
        res = []
        def traversal(root: TreeNode):
            if root == None:
                return
            traversal(root.left)
            res.append(root.val)
            traversal(root.right)
        traversal(root)
        #统计一个有序列表的最小差值
        all_subs = []
        for i in range(len(res)-1):
            all_subs.append(res[i+1]-res[i])
            
        return min(all_subs)

501. 二叉搜索树中的众数

给定一个有相同值的二叉搜索树(BST),找出 BST 中的所有众数(出现频率最高的元素)。

假定 BST 有如下定义:

  • 结点左子树中所含结点的值小于等于当前结点的值
  • 结点右子树中所含结点的值大于等于当前结点的值
  • 左子树和右子树都是二叉搜索树

例如:
给定 BST [1,null,2,2],

   1
    \
     2
    /
   2

返回[2].

代码:

class Solution:
    def findMode(self, root: TreeNode) -> List[int]:
        res = []
        def traversal(root: TreeNode):
            if root == None:
                return
            traversal(root.left)
            res.append(root.val)
            traversal(root.right)
        traversal(root)
        temp_set = {}
        for val in res:
            if val in temp_set:
                temp_set[val] += 1
            else:
                temp_set[val] = 1
        results = []
        for key, value in temp_set.items():
            if value == max(temp_set.values()):
                results.append(key)
        return results

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

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

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

示例 1:

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

 代码:

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        """
        采用后续遍历
        如果找到一个节点,发现左子树出现结点p,右子树出现节点q,或者 左子树出现结点q,
        右子树出现节点p,那么该节点就是节点p和q的最近公共祖先。
        """
        #1.0 确定返回值及其参数
        def recursion(root: 'TreeNode', p: 'TreeNode', q: 'TreeNode'):
            #2.0 确定停止条件,或者找到p,q中的一个就去返回
            if root == None or root == p or root == q:
                return root
            left_node = recursion(root.left,p,q)
            right_node = recursion(root.right,p,q)
            #3.0代码的逻辑
            """
            ---->如果left_node与right_node都不为空,说明该root就是要找的公共祖先
            ---->如果left_node不为空,而right_node为空,说明公共祖先位于root的左子节点上
            ---->如果left_node为空,而right_node不为空,说明公共祖先位于root的右子节点上
            """
            if left_node != None and right_node != None:
                return root
            
            if left_node != None and right_node == None:
                return left_node
            if left_node == None and right_node != None:
                return right_node
        return recursion(root,p,q)

235. 二叉搜索树的最近公共祖先

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

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

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

示例 1:

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

 代码:

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        """
        采用后续遍历
        如果找到一个节点,发现左子树出现结点p,右子树出现节点q,或者 左子树出现结点q,
        右子树出现节点p,那么该节点就是节点p和q的最近公共祖先。
        """
        #1.0 确定返回值及其参数
        def recursion(root: 'TreeNode', p: 'TreeNode', q: 'TreeNode'):
            #2.0 确定停止条件,或者找到p,q中的一个就去返回
            if root == None or root == p or root == q:
                return root
            left_node = recursion(root.left,p,q)
            right_node = recursion(root.right,p,q)
            #3.0代码的逻辑
            """
            ---->如果left_node与right_node都不为空,说明该root就是要找的公共祖先
            ---->如果left_node不为空,而right_node为空,说明公共祖先位于root的左子节点上
            ---->如果left_node为空,而right_node不为空,说明公共祖先位于root的右子节点上
            """
            if left_node != None and right_node != None:
                return root
            
            if left_node != None and right_node == None:
                return left_node
            if left_node == None and right_node != None:
                return right_node
        return recursion(root,p,q)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值