【Python3】 LeetCode 7月挑战题目之13 - Same Tree

大家好,我是一个喜欢研究算法、机械学习和生物计算的小青年,我的CSDN博客是:一骑代码走天涯
如果您喜欢我的笔记,那么请点一下关注、点赞和收藏。如果內容有錯或者有改进的空间,也希望在评论让我知道。😄

第十三天问:Same Tree

题目连接: https://leetcode.com/explore/challenge/card/july-leetcoding-challenge/545/week-2-july-8th-july-14th/3389/

这题的要求很容易理解,就是假设给你兩棵只包含整数的二叉树,编写一个函数来检验它们俩是否完全一样 (包括数值上和结构上)

题目&示例 (引用自LeetCode)

Given two binary trees, write a function to check if they are the same or not.
Two binary trees are considered the same if they are structurally identical and the nodes have the same value.

Example 1:

Input:     1         1
          / \       / \
         2   3     2   3

        [1,2,3],   [1,2,3]

Output: true

Example 2:

Input:     1         1
          /           \
         2             2

        [1,2],     [1,null,2]

Output: false

Example 3:

Input:     1         1
          / \       / \
         2   1     1   2

        [1,2,1],   [1,1,2]

Output: false

解题思路

对于这道问题,想到至少有三种解法。第一种是最直观的,就是用while-loop一个个节点 (从上到下,从左到右) 查看,如果一发现不对就直接返回False。第二种方法和第一种相同,不过用递归 (Recursion) 来表达 (参考自LeetCode答案)。

第三种方法,就是利用二叉树的遍历 (Traversal) 进行树的比较,而遍历又分为三种手法:前序(Pre-order)中序(In-order)后序(Post-order),但当中 中序(In-order) 並不适合解这道题目

那么,先简单介绍一下这三种遍历有什么不一样:

前序(Pre-order):从根节点开始遍历,然后昰左边的子树一路往左遍历到最底层。到底后返回前一个节点往右边走,如果中间的节点左边可以走就再往左,到底再往右,直到返回根节点就往右走,重复以上步骤。
在这里插入图片描述
后序(Post-order):从最左边子树底层开始遍历,每次打印后就返回前一个节点往右边走,如果中间的节点左边可以走就再往左,到底再往右,如果返回根节点就不打印,直接往右走重复以上步骤,最后才打印根节点。
在这里插入图片描述中序(In-order):从最左边子树底层开始遍历,每次打印完最左边节点就打印前一个节点,然后往该节点右边走重复上述动作,直到全部打印就返回再前一个节点,再重复直到全部节点打印完毕。
在这里插入图片描述其中,中序法有个问题,就是如果两棵树各自只有一边 (全左边或全右边) 有节点,而且树的节点数值一模一样,那遍历之后两个答案就会一样。
在这里插入图片描述

代码一 (迭代,逐个对比)

时间复杂度:O( N N N)
空间复杂度:O( log ⁡ N \log N logN)

# 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 isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
        if p is None and q is None:
            return True
        elif p is None or q is None:
            return False
        else:
            # <Method 1: check nodes one by one>
            current_p = [p]
            current_q = [q]
            while not all(x is None for x in current_p) or \
            not all(y is None for y in current_q):
                p_next = []
                q_next = []
                for i in range(len(current_p)):
                    if current_p[i] is None and current_q[i] is None:
                        continue
                    elif current_p[i] is None or current_q[i] is None:
                        return False
                    elif current_p[i].val == current_q[i].val:
                        p_next.append(current_p[i].left)
                        p_next.append(current_p[i].right)
                        q_next.append(current_q[i].left)
                        q_next.append(current_q[i].right)
                    else:
                        return False
                current_p = p_next
                current_q = q_next
            return True           

代码二 (递归法,引用自LeetCode官方答案)

时间复杂度:O( N N N)
空间复杂度:O( log ⁡ N \log N logN)

class Solution:
    def isSameTree(self, p, q):
        """
        :type p: TreeNode
        :type q: TreeNode
        :rtype: bool
        """    
        # p and q are both None
        if not p and not q:
            return True
        # one of p and q is None
        if not q or not p:
            return False
        if p.val != q.val:
            return False
        return self.isSameTree(p.right, q.right) and \
               self.isSameTree(p.left, q.left)

代码三 (遍历法,包括前序、中序、后序)

时间复杂度:O( N N N)
空间复杂度:O( N N N)

# 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 isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
        # <Method 2: Trasveral>
        p_array = self.xTraversal(p) #xTraversal: {PreorderTraversal,inorderTraversal,PostorderTraversal}
        q_array = self.xTraversal(q) #xTraversal: {PreorderTraversal,inorderTraversal,PostorderTraversal}
        if p_array == q_array:
            return True
        else:
            False
        
    def PreorderTraversal(self, root):
        res = []
        if root:
            res.append(root.val)
            res = res + self.PreorderTraversal(root.left)
            res = res + self.PreorderTraversal(root.right)
        else:
            res.append(None)
        return res
    
    def inorderTraversal(self, root): #不适合这题目
        res = []
        if root:
            res = self.inorderTraversal(root.left)
            res.append(root.val)
            res = res + self.inorderTraversal(root.right)
        # else:
        #     res.append(None)
        return res
    
    def PostorderTraversal(self, root):
        res = []
        if root:
            res = self.PostorderTraversal(root.left)
            res = res + self.PostorderTraversal(root.right)
            res.append(root.val)
        else:
            res.append(None)
        return res

Reference/参考资料

  1. https://leetcode.com/articles/same-tree/#
  2. https://www.tutorialspoint.com/python_data_structure/python_tree_traversal_algorithms.htm
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值