刷题-二叉树

二叉树的中序遍历

class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        # 中序:左中右
        ans, stk = [], [] # 用栈来存中间结果 先进后出
        while root or stk:
            if root:
                stk.append(root) # 根节点先入栈
                root = root.left # 不断访问左子树、直到最左的叶子节点/中节点
            else:
                root = stk.pop() # 先出最左边/中节点,先进后出
                ans.append(root.val)    # 保存结果
                root = root.right  # 出一个就可以取它的右节点了、因为左节点和根节点(左节点出的时候其没有右节点、所以root回到根节点)已经出栈了
        return ans

二叉树的最大深度

class Solution:
    def maxDepth(self, root: Optional[TreeNode]) -> int:
        if not root: return 0
        queue, res = [root], 0
        while queue:
            tmp = []
            for node in queue: # 用层次遍历的方式得到最大深度
                if node.left:
                    tmp.append(node.left)   # tmp存的是下一层的节点
                if node.right:
                    tmp.append(node.right)
            queue = tmp
            res += 1 # 每一层访问完深度+1
        return res

翻转二叉树

class Solution:
    def invertTree(self, root: TreeNode) -> TreeNode:
        if not root: return root
        self.invertTree(root.left)
        self.invertTree(root.right)
        root.left, root.right = root.right, root.left   # 后序遍历(左右中)的方式迭代
        return root

对称二叉树

class Solution:
    def isSymmetric(self, root: Optional[TreeNode]) -> bool:
        def recur(L, R):
            if not L and not R: return True
            if not L or not R or L.val != R.val: return False
            return recur(L.left, R.right) and recur(L.right, R.left)    # 先序遍历(中左右)的方式迭代
        return not root or recur(root.left, root.right)

二叉树的直径

二叉树的 直径 是指树中任意两个节点之间最长路径的 长度(父子节点之间的长度是1)

class Solution:
    def diameterOfBinaryTree(self, root: Optional[TreeNode]) -> int:
        ans = 0
        def dfs(node):
            if node is None:
                return -1
            l_len = dfs(node.left) + 1 # 如果有左节点、左子树长度+1
            r_len = dfs(node.right) + 1 
            nonlocal ans 
            ans = max(ans, l_len + r_len) # 只记录最大值
            return max(l_len, r_len) # 返回以该节点为起点的最大值 后序遍历
        dfs(root)
        return ans

二叉树的层序遍历

class Solution:
    def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
        if not root:
            return []
        q = deque([root])  # 记录每一层的节点
        res = []
        while q:
            tmp = []
            n = len(q)
            for i in range(n):  # 遍历当前层的节点
                i = q.popleft() # 队列、先进先出
                if i.left:
                    q.append(i.left)  # 下一层节点依次 入队列
                if i.right:
                    q.append(i.right)
                tmp.append(i.val) # 记录当前层的单个值
            res.append(tmp) # 记录当前层的所有值
        return res

将有序数组转换为二叉搜索树

class Solution:
    def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
        return self.build(nums, 0, len(nums) - 1)

    def build(self, nums, l, r):
        if l > r:
            return None
        mid = (l + r) // 2
        ans = TreeNode(nums[mid])   # 先序遍历、先固定头节点
        ans.left = self.build(nums, l, mid - 1)  # 左子树
        ans.right = self.build(nums, mid + 1, r)  # 右子树
        return ans

验证二叉搜索树

class Solution:
    def isValidBST(self, root: Optional[TreeNode], left=float('-inf'), right=float('inf')) -> bool:
        if root is None:
            return True  # 空节点始终是合法的BST
        x = root.val  # 当前节点的值
        return left < x < right and \  # 当前节点的值必须在(left, right)范围内
                self.isValidBST(root.left, left, x) and \  # 递归检查左子树,更新上界为当前节点值
                self.isValidBST(root.right, x, right)  # 递归检查右子树,更新下界为当前节点值
                # 第二步比较的是 left节点是否小于父节点值
                # 第三步比较的是 right节点是否大于父节点值

二叉搜索树中第k小的值

class Solution:
    def kthSmallest(self, root: Optional[TreeNode], k: int) -> int:
        # 使用中序遍历找到第 k 小的元素
        
        def dfs(root):
            if not root:  # 如果当前节点为空,则返回(递归终止条件)
                return
            dfs(root.left)  # 递归访问左子树(中序遍历的左部分)

            if self.k == 0:  # 如果已经找到了第 k 小的元素,提前退出递归
                return

            self.k -= 1  # 处理当前节点,减小 k 的值
            if self.k == 0:  # 如果 k 减为 0,说明当前节点是第 k 小的元素
                self.res = root.val  # 记录结果
            
            dfs(root.right)  # 递归访问右子树(中序遍历的右部分)
        
        self.k = k  # 初始化 k
        dfs(root)  # 开始中序遍历
        return self.res  # 返回找到的第 k 小的元素

二叉树的右视图

class Solution:
    def rightSideView(self, root: Optional[TreeNode]) -> List[int]:
        # 层序遍历只要最后一个值
        if not root:
            return []
        q = deque([root])
        res = []
        while q:
            l = len(q)
            for i in range(l):
                n = q.popleft()
                if n.left:
                    q.append(n.left)
                if n.right:
                    q.append(n.right)
            res.append(n.val)
        return res

二叉树展开为链表

class Solution:
    node = None  # 类变量,用于跟踪链接链表的当前节点

    def flatten(self, root: Optional[TreeNode]) -> None:
        """
        不返回任何内容,而是就地修改 root
        """
        if not root:  # 如果当前节点为空,直接返回
            return
        
        if not self.node:  # 如果 self.node 为空,初始化为当前 root
            self.node = root
        else:
            self.node.left = None  # 将当前节点的左子指针设为空
            self.node.right = root  # 将当前节点的右子指针指向当前的 root
            self.node = self.node.right  # 更新 self.node 为新的右子节点
        
        # 保存右子树的引用,因为递归过程中右子树会被覆盖
        r = root.right 
        
        # 递归展平左子树
        self.flatten(root.left)
        
        # 递归展平右子树(注意这里传入的是保存在 r 中的原来的右子树)
        self.flatten(r)

从前序和中序遍历序列构造二叉树

class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
        # 如果前序遍历序列为空,返回 None(递归终止条件)
        if not preorder:
            return None
        
        # 找到根节点在中序遍历中的位置
        left_size = inorder.index(preorder[0])  # 根节点(前序遍历第一个元素)在中序遍历中的索引,它划分了左子树和右子树
        
        # 递归构建左子树
        left = self.buildTree(
            preorder[1:1 + left_size],  # 左子树的前序遍历序列
            inorder[:left_size]  # 左子树的中序遍历序列
        )
        
        # 递归构建右子树
        right = self.buildTree(
            preorder[1 + left_size:],  # 右子树的前序遍历序列
            inorder[1 + left_size:]  # 右子树的中序遍历序列
        )
        
        # 返回构建的树的根节点
        return TreeNode(
            preorder[0],  # 当前树的根节点值(前序遍历的第一个值)
            left,  # 构建好的左子树
            right  # 构建好的右子树
        )

路径总和

给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum 的 路径 的数目。

class Solution:
    def pathSum(self, root: Optional[TreeNode], targetSum: int) -> int:
        # 内部函数,用于计算从当前节点开始,和为targetSum的所有路径数
        def rootSum(root, targetSum):
            if root is None:
                return 0  # 如果当前节点为空,返回0(代表没有路径)
            
            ret = 0
            if root.val == targetSum:
                ret += 1  # 如果当前节点值等于目标和,路径+1
            
            # 递归计算左子树的路径数
            ret += rootSum(root.left, targetSum - root.val)
            # 递归计算右子树的路径数
            ret += rootSum(root.right, targetSum - root.val)
            
            return ret  # 返回从当前节点开始的所有路径数

        if root is None:
            return 0  # 如果根节点为空,返回0
        
        # 计算从当前根节点开始的路径和
        ret = rootSum(root, targetSum)
        # 递归计算左子树中的路径和
        ret += self.pathSum(root.left, targetSum)
        # 递归计算右子树中的路径和
        ret += self.pathSum(root.right, targetSum)
        
        return ret  # 返回所有路径的总数

二叉树的最近公共祖先

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        # 如果当前节点是None,或者是节点p或q中的任意一个,直接返回当前节点
        if root in (None, p, q):
            return root
        
        # 递归查找左子树中的LCA
        left = self.lowestCommonAncestor(root.left, p, q)
        # 递归查找右子树中的LCA
        right = self.lowestCommonAncestor(root.right, p, q)
        
        # 如果左子树和右子树都找到了对应的节点,说明当前节点是LCA
        if left and right:
            return root
        
        # 返回找到的非空子树的结果
        return left or right

二叉树中的最大路径和

class Solution:
    def maxPathSum(self, root: TreeNode, ok=True) -> int:
        if not root:
            return 0  # 如果当前节点为空,返回0(递归终止条件)

        # 递归计算左子树和右子树的最大路径和(不允许跨越根节点)
        left = self.maxPathSum(root.left, False)  
        right = self.maxPathSum(root.right, False)

        # 计算经过当前节点的路径和,并更新全局最大路径和
        self.maxSum = max(getattr(self, 'maxSum', float('-inf')), left + root.val + right)
        
        # 当从根节点开始时返回最大路径和,否则只返回单侧最大路径和
        return self.maxSum if ok else max(root.val + max(left, right), 0)   # 这里的root.val 和 上一行的  root.val 不是同一个

对于最初的调用(ok=True),返回 self.maxSum,表示整个树中的最大路径和。

对于递归调用(ok=False),返回的是从当前节点出发的最大单侧路径和(大于等于0)。

### RT-DETRv3 网络结构分析 RT-DETRv3 是一种基于 Transformer 的实时端到端目标检测算法,其核心在于通过引入分层密集正监督方法以及一系列创新性的训练策略,解决了传统 DETR 模型收敛慢和解码器训练不足的问题。以下是 RT-DETRv3 的主要网络结构特点: #### 1. **基于 CNN 的辅助分支** 为了增强编码器的特征表示能力,RT-DETRv3 引入了一个基于卷积神经网络 (CNN) 的辅助分支[^3]。这一分支提供了密集的监督信号,能够与原始解码器协同工作,从而提升整体性能。 ```python class AuxiliaryBranch(nn.Module): def __init__(self, in_channels, out_channels): super(AuxiliaryBranch, self).__init__() self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1) self.bn = nn.BatchNorm2d(out_channels) def forward(self, x): return F.relu(self.bn(self.conv(x))) ``` 此部分的设计灵感来源于传统的 CNN 架构,例如 YOLO 系列中的 CSPNet 和 PAN 结构[^2],这些技术被用来优化特征提取效率并减少计算开销。 --- #### 2. **自注意力扰动学习策略** 为解决解码器训练不足的问题,RT-DETRv3 提出了一种名为 *self-att 扰动* 的新学习策略。这种策略通过对多个查询组中阳性样本的标签分配进行多样化处理,有效增加了阳例的数量,进而提高了模型的学习能力和泛化性能。 具体实现方式是在训练过程中动态调整注意力权重分布,确保更多的高质量查询可以与真实标注 (Ground Truth) 进行匹配。 --- #### 3. **共享权重解编码器分支** 除了上述改进外,RT-DETRv3 还引入了一个共享权重的解编码器分支,专门用于提供密集的正向监督信号。这一设计不仅简化了模型架构,还显著降低了参数量和推理时间,使其更适合实时应用需求。 ```python class SharedDecoderEncoder(nn.Module): def __init__(self, d_model, nhead, num_layers): super(SharedDecoderEncoder, self).__init__() decoder_layer = nn.TransformerDecoderLayer(d_model=d_model, nhead=nhead) self.decoder = nn.TransformerDecoder(decoder_layer, num_layers=num_layers) def forward(self, tgt, memory): return self.decoder(tgt=tgt, memory=memory) ``` 通过这种方式,RT-DETRv3 实现了高效的目标检测流程,在保持高精度的同时大幅缩短了推理延迟。 --- #### 4. **与其他模型的关系** 值得一提的是,RT-DETRv3 并未完全抛弃经典的 CNN 技术,而是将其与 Transformer 结合起来形成混合架构[^4]。例如,它采用了 YOLO 系列中的 RepNCSP 模块替代冗余的多尺度自注意力层,从而减少了不必要的计算负担。 此外,RT-DETRv3 还借鉴了 DETR 的一对一匹配策略,并在此基础上进行了优化,进一步提升了小目标检测的能力。 --- ### 总结 综上所述,RT-DETRv3 的网络结构主要包括以下几个关键组件:基于 CNN 的辅助分支、自注意力扰动学习策略、共享权重解编码器分支以及混合编码器设计。这些技术创新共同推动了实时目标检测领域的发展,使其在复杂场景下的表现更加出色。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值