代码随想录算法训练营Day14

在这里插入图片描述

一、力扣226.翻转二叉树【easy】

题目链接:力扣226.翻转二叉树在这里插入图片描述
视频链接:代码随想录

1、思路

  • 利用递归,要想清楚三部曲:
    • 确定递归函数的参数值和返回值:返回根节点root
    • 确定终止条件:碰到空节点停止循环
    • 确定单层递归的逻辑——取决于我们是什么遍历
      • 如果是前序遍历,先交换节点的左右孩子,递归处理交换后的左右子树
  • 时间复杂度: O ( n ) O(n) O(n),其中 n 是二叉树的节点数,每个节点恰好被访问一次

2、代码

class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if not root:
            return None
        # 先交换当前节点的左右子树
        root.left , root.right = root.right , root.left
        # 递归处理交换后的左右子树
        self.invertTree(root.left)
        self.invertTree(root.right)
        return root

3、代码问题

  • self.invertTree(root)
    • 无限递归:每次处理当前节点时,又会重新调用自身处理同一个节点,形成死循环。
    • 栈溢出:递归没有终止条件,最终引发 RecursionError。

三、力扣104.二叉树的最大深度【easy】

题目链接:力扣104.二叉树的最大深度
视频链接:灵茶山艾府

1、思路

  • 递归
  • 也可以迭代——队列
  • 时间复杂度: O ( n ) O(n) O(n)

2、代码

class Solution:
    def maxDepth(self, root: Optional[TreeNode]) -> int:
        if root is None:
            return 0
        left_depth = self.maxDepth(root.left)
        right_depth = self.maxDepth(root.right)
        return max(left_depth , right_depth) + 1

三、力扣100.相同的树【easy】

题目链接:力扣100.相同的树
视频链接:灵茶山艾府

1、思路

  • 递归终止条件:
    • 当 p 或 q 为空时,只有两者同时为空才返回 True
  • 递归比较逻辑:
    • 当前节点值必须相同
    • 左子树和右子树必须分别递归比较
  • 时间复杂度: O ( n ) O(n) O(n)

2、代码

class Solution:
    def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
        # 终止条件:当p、q都为None,此时p is q return true
        if p is None or q is None:
            return p is q
        return p.val == q.val and self.isSameTree(p.left , q.left) and self.isSameTree(p.right , q.right)

四、力扣101.对称二叉树【easy】

题目链接:力扣101.对称二叉树
视频链接:代码随想录

1、思路

  • 对于二叉树是否对称,要比较的是根节点的左子树与右子树是不是相互翻转的,比较的是两个子树的里侧和外侧的元素是否相等。如图所示:在这里插入图片描述
  • 递归三部曲
    • 确定递归函数的参数和返回值:左子树节点和右子树节点。
    • 终止条件:左右节点都为空
    • 单层递归的逻辑 :
      • 比较二叉树外侧是否对称:传入的是左节点的左孩子,右节点的右孩子。
      • 比较内侧是否对称,传入左节点的右孩子,右节点的左孩子。
      • 如果左右都对称就返回true ,有一侧不对称就返回false 。
  • 时间复杂度: O ( n ) O(n) O(n)

2、代码

  • 灵茶山艾府
class Solution:
    def isMirror(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
        # 终止条件:当p、q都为None,此时p is q return true
        #如果pq不为None,这个if不成立,不会执行return语句
        if p is None or q is None:
            return p is q
        return p.val == q.val and self.isMirror(p.left , q.right) and self.isMirror(p.right , q.left)

    def isSymmetric(self, root: Optional[TreeNode]) -> bool:
        return self.isMirror(root.left , root.right)
class Solution:
    def isSametree(self,p: Optional[TreeNode] , q: Optional[TreeNode]) -> bool:
        if p is None or q is None:
            return p is q
        return p.val == q.val and self.isSametree(p.left , q.left) and self.isSametree(p.right , q.right)

    def isSubtree(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool:
        if root is None:
            return False
        return self.isSametree(root , subRoot) or \
            self.isSubtree(root.left , subRoot) or \
            self.isSubtree(root.right , subRoot)

3、代码问题

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

五、力扣559.N叉树的最大深度【easy】

题目链接:力扣104.二叉树的最大深度
视频链接:代码随想录在这里插入图片描述

1、思路

  • 这是二叉树最大深度的拓展
  • 时间复杂度: O ( n ) O(n) O(n)

2、代码

class Solution:
    def maxDepth(self, root: 'Node') -> int:
        if not root:
            return 0
        
        max_depth = 1
        for child in root.children:
            max_depth = max(max_depth , self.max_depth(child) +1)

六、力扣111.二叉树的最小深度【easy】

题目链接:力扣111.二叉树的最小深度
视频链接:代码随想录

1、思路

  • 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。注意是叶子节点。
  • 只有当左右孩子都为空的时候,才说明遍历到最低点了。如果其中一个孩子不为空则不是最低点
  • 时间复杂度: O ( n ) O(n) O(n)

2、代码

class Solution:
    def getDepth(self,node):
        if node is None:
            return 0 
        leftDepth = self.getDepth(node.left) 
        rightDepth = self.getDepth(node.right)
        if node.left is None and node.right is not None:
            return 1 + rightDepth
        if node.right is None and node.left is not None:
            return 1 + leftDepth
        return 1 + min(leftDepth , rightDepth)

    def minDepth(self, root: Optional[TreeNode]) -> int:
        return self.getDepth(root)
  • 灵神
class Solution:
    def minDepth(self, root: Optional[TreeNode]) -> int:
        ans = inf
        def dfs(node: Optional[TreeNode], cnt: int) -> None:
            if node is None:
                return
            cnt += 1
            if node.left is node.right:  # node 是叶子
                nonlocal ans
                ans = min(ans, cnt)
                return
            dfs(node.left, cnt)
            dfs(node.right, cnt)
        dfs(root, 0)
        return ans if root else 0

3、代码问题

  • 是我
    在这里插入图片描述
  • dfs 函数的核心任务是遍历所有可能的路径并更新最小深度,而不是直接返回计算结果。它的作用是通过递归访问所有节点,并在遇到叶子节点时更新外部变量 ans。因此,它的返回值无需携带信息,只需完成遍历即可。
  • 叶子节点:if node.left is None and node.right is None
    • Python中的None是一个特殊的单例对象,所有赋值为None的变量都指向同一个内存地址。
    • 当节点的左子节点和右子节点均为None时,node.leftnode.right实际上是同一个对象,node.left is node.right会返回True
  • nonlocal关键字的作用是声明一个变量属于外层嵌套函数的作用域(而非全局作用域)
    • global:声明变量属于全局作用域(即模块级别
    • 在嵌套函数中修改外层函数的变量时,必须使用nonlocal,否则Python会将其视为局部变量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值