[Leetcode][python]Symmetric Tree/对称二叉树

题目大意

判断一个树是否左右对称

解题思路

非递归解法

按层遍历,每一层检查一下是否对称。

递归解法

其中左子树和右子树对称的条件:
两个节点值相等,或者都为空
左节点的左子树和右节点的右子树对称
左节点的右子树和右节点的左子树对称

代码

递归(清晰易懂版)

class Solution(object):
    def judge(self, p, q):
        if p == None and q == None: 
            return True
        if p and q and p.val == q.val: # 如果一边有一边没有那么直接返回False
            return self.judge(p.left, q.right) and self.judge(p.right, q.left)
        return False

    def isSymmetric(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        if root:
            return self.judge(root.left, root.right)
        return True

递归(超简洁版)

运算速度慢

class Solution(object):
    def isSymmetric(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        def isSym(L,R):
            if L and R and L.val == R.val: 
                return isSym(L.left, R.right) and isSym(L.right, R.left)
            return L == R
        return isSym(root, root)

迭代

换成数组进行判断,运算速度只超过0.5%的人

class Solution(object):
    def isSymmetric(self, root):
        queue = [root]
        while queue:
            values = [i.val if i else None for i in queue]
            if values != values[::-1]: return False
            queue = [child for i in queue if i for child in (i.left, i.right)]
        return True

总结

递归与迭代的关系

1) 递归中一定有迭代,但是迭代中不一定有递归,大部分可以相互转换。
2) 能用迭代的不用递归,递归调用函数,浪费空间,并且递归太深容易造成堆栈的溢出.

函数嵌套

python允许函数嵌套,也就是说我们可以在函数内部定义一个函数,这些函数都遵循各自的作用域和生命周期规则。

<think>好,我现在需要帮用户整理LeetCode上几个二叉树相关问题的Python3答案。用户提到的题目包括中序遍历、最大深度、翻转二叉树对称二叉树二叉树的直径和层序遍历。我得一个一个来,先回忆每个题目的要求和常用解法。 首先,中序遍历。这应该是基础题,要求按照左根右的顺序遍历递归方法比较简单,但用户可能需要迭代法,因为有时候面试会要求。递归的话,定义一个辅助函数,先遍历左子树,然后访问根节点,再遍历右子树。迭代的话需要用栈,尽可能往左走,然后弹出栈顶,处理节点,再转向右子树。两种方法都要写出来。 接下来是最大深度。最大深度就是根节点到最远叶子节点的路径长度。递归的话,左右子树的最大深度取较大者加一。也可以用BFS层序遍历,记录层数,每处理一层就加一,直到队列为空。两种方法都行,但递归更简洁。 翻转二叉树,也就是每个节点的左右子树交换。可以用递归,先翻转左右子树,然后交换。或者用队列进行层序翻转,每次取出节点交换左右孩子,然后入队非空的孩子。递归应该更直接。 对称二叉树,判断是否镜像对称。可以用递归,比较左子树的左和右子树的右,以及左子树的右和右子树的左。或者用队列迭代,每次取出两个节点比较,然后按顺序入队它们的左右孩子。递归方法可能更直观。 二叉树的直径,直径是任意两节点间最长路径的长度。这个路径可能不经过根节点,所以需要计算每个节点的左右子树高度之和,并更新最大值。后序遍历,计算左右子树的高度,取较大者加一,同时维护一个全局变量记录最大直径。注意直径是边数,即节点数减一,所以计算左右高度之和即可。 层序遍历,需要按层输出节点的值。用队列实现BFS,每次处理一层,记录当前层的节点数,循环处理每个节点,将其子节点入队,并将当前层的值存入结果列表。这题相对基础,但要注意处理每一层的节点数量。 现在要确保每个解法都是Python3的代码,符合题目要求,并且效率较高。递归方法可能会有栈溢出的问题,但对于LeetCode的测试用例通常没问题。迭代方法更安全一些。对于每个题目,需要给出两种解法吗?比如中序遍历递归和迭代,或者选一种典型的。用户可能需要多种解法,所以尽量提供两种,如果适用的话。例如,中序遍历递归和迭代,最大深度的递归和BFS,翻转二叉树递归和迭代,对称二叉树递归和迭代,直径的后序遍历递归,层序遍历的BFS。 然后,检查每个解法的正确性。比如,翻转二叉树递归解法是否正确交换左右子树。对称二叉树递归条件是否正确,比较左左和右右,左右和右左。直径的计算是否在递归过程中更新最大值,初始值设为0是否正确。 另外,注意代码格式,使用正确的语法,比如在Python中类的定义,函数参数,缩进等。比如,中序遍历递归辅助函数可能需要修改结果列表,或者将结果作为参数传递。不过通常用一个实例变量或者嵌套函数来捕获变量。比如在递归函数中,传入结果列表,然后修改它。 比如中序遍历递归代码: def inorderTraversal(root): res = [] def helper(node): if not node: return helper(node.left) res.append(node.val) helper(node.right) helper(root) return res 这样是正确的。而迭代方法则需要用栈,循环处理左子树,然后弹出处理,再处理右子树。 最大深度的递归: def maxDepth(root): if not root: return 0 return 1 + max(maxDepth(root.left), maxDepth(root.right)) 层序遍历的BFS: def levelOrder(root): if not root: return [] res = [] queue = deque([root]) while queue: level = [] for _ in range(len(queue)): node = queue.popleft() level.append(node.val) if node.left: queue.append(node.left) if node.right: queue.append(node.right) res.append(level) return res 对称二叉树递归解法: def isSymmetric(root): def check(left, right): if not left and not right: return True if not left or not right: return False return left.val == right.val and check(left.left, right.right) and check(left.right, right.left) return check(root, root) 注意这里传入根节点的左右子树,或者直接比较根的两个副本,比如根节点的左和右。 二叉树的直径问题,需要一个全局变量记录最大值,然后在递归计算高度的同时更新这个最大值: class Solution: def diameterOfBinaryTree(self, root: TreeNode) -> int: self.max_diameter = 0 def depth(node): if not node: return 0 left = depth(node.left) right = depth(node.right) self.max_diameter = max(self.max_diameter, left + right) return 1 + max(left, right) depth(root) return self.max_diameter 这里每次递归返回的是当前节点的高度,而直径是左右高度之和,所以在递归过程中更新最大值。注意这里的直径是边数,即路径长度为左高度+右高度,所以不需要减一。 翻转二叉树递归解法: def invertTree(root): if not root: return None left = invertTree(root.left) right = invertTree(root.right) root.left, root.right = right, left return root 或者更简洁的写法: def invertTree(root): if root: root.left, root.right = invertTree(root.right), invertTree(root.left) return root 这两种写法都是正确的,但要注意Python中的执行顺序,右边的表达式先求值,所以交换是正确的。 总结每个问题的解法,确保代码正确,然后按照用户的要求,用中文解释每个解法的思路,给出代码示例,并注意格式中的数学表达式用$...$,独立公式用$$...$$,但可能在这题中用得比较少。不过用户的问题是关于代码的,所以可能数学表达式不多,可能涉及复杂度分析的时候需要。 最后,将每个问题的答案按用户列出的顺序整理,每个问题给出一种或两种解法,并简要说明思路和注意点。确保结构清晰,步骤明确,帮助用户理解每个问题的解决方法。</think>以下是LeetCode二叉树常见问题的Python3解答及解析: --- ### 一、二叉树的中序遍历 **题目要求**:返回节点值的`左 -> 根 -> 右`顺序列表。 #### 1. 递归解法 ```python def inorderTraversal(root): res = [] def helper(node): if not node: return helper(node.left) res.append(node.val) helper(node.right) helper(root) return res ``` **时间复杂度**:$O(n)$,每个节点访问一次。 #### 2. 迭代解法(栈) ```python def inorderTraversal(root): res = [] stack = [] curr = root while curr or stack: while curr: stack.append(curr) curr = curr.left curr = stack.pop() res.append(curr.val) curr = curr.right return res ``` **核心思路**:利用栈模拟递归,优先访问左子树。 --- ### 二、二叉树的最大深度 **题目要求**:返回从根节点到最远叶子节点的最长路径上的节点数。 #### 递归解法 ```python def maxDepth(root): if not root: return 0 return 1 + max(maxDepth(root.left), maxDepth(root.right)) ``` **时间复杂度**:$O(n)$,每个节点遍历一次。 --- ### 三、翻转二叉树 **题目要求**:交换每个节点的左右子树。 #### 递归解法 ```python def invertTree(root): if root: root.left, root.right = invertTree(root.right), invertTree(root.left) return root ``` **核心思路**:递归交换左右子树,直到叶子节点。 --- ### 四、对称二叉树 **题目要求**:判断二叉树是否镜像对称。 #### 递归解法 ```python def isSymmetric(root): def check(left, right): if not left and not right: return True if not left or not right: return False return left.val == right.val and check(left.left, right.right) and check(left.right, right.left) return check(root.left, root.right) if root else True ``` **核心思路**:比较左子树的左节点与右子树的右节点,反之亦然。 --- ### 五、二叉树的直径 **题目要求**:返回任意两节点间最长路径的长度(边数)。 #### 后序遍历解法 ```python class Solution: def diameterOfBinaryTree(self, root): self.max_diameter = 0 def depth(node): if not node: return 0 left = depth(node.left) right = depth(node.right) self.max_diameter = max(self.max_diameter, left + right) return 1 + max(left, right) depth(root) return self.max_diameter ``` **核心思路**:对每个节点计算左右子树高度之和,更新最大值。 --- ### 六、二叉树的层序遍历 **题目要求**:按层返回节点值的二维列表。 #### BFS队列解法 ```python from collections import deque def levelOrder(root): if not root: return [] res = [] queue = deque([root]) while queue: level_size = len(queue) current_level = [] for _ in range(level_size): node = queue.popleft() current_level.append(node.val) if node.left: queue.append(node.left) if node.right: queue.append(node.right) res.append(current_level) return res ``` **时间复杂度**:$O(n)$,每个节点入队出队一次。 --- ### 总结 1. **递归**是二叉树问题的常用解法,但需注意栈溢出风险。 2. **迭代**解法(如栈、队列)更适用于大数据量。 3. 大部分问题的时间复杂度为$O(n)$,空间复杂度取决于递归深度或队列大小。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值