当前位置: 首页 > news >正文

代码随想录第17天:二叉树

一、二叉搜索树的最近公共祖先(Leetcode 235)

由于是二叉搜索树,节点的值有严格的顺序关系:左子树的节点值都小于父节点,右子树的节点值都大于父节点。利用这一点,可以在树中更高效地找到最低公共祖先。

class Solution:
    def traversal(self, cur, p, q):
        # 递归的基本情况:当前节点为空,返回 None
        if cur is None:
            return cur
        
        # 如果当前节点的值大于 p 和 q 的值,说明 p 和 q 都在左子树中
        if cur.val > p.val and cur.val > q.val:  # 左
            left = self.traversal(cur.left, p, q)  # 在左子树中递归查找
            if left is not None:
                return left  # 如果左子树中找到了节点,返回该节点

        # 如果当前节点的值小于 p 和 q 的值,说明 p 和 q 都在右子树中
        if cur.val < p.val and cur.val < q.val:  # 右
            right = self.traversal(cur.right, p, q)  # 在右子树中递归查找
            if right is not None:
                return right  # 如果右子树中找到了节点,返回该节点

        # 如果左右子树都不为空,说明 p 和 q 分别在左右子树中
        return cur  # 返回当前节点,因为当前节点就是它们的最低公共祖先

    def lowestCommonAncestor(self, root, p, q):
        return self.traversal(root, p, q)  # 从根节点开始查找 p 和 q 的最低公共祖先

二、二叉搜索树中的插入操作(Leetcode 701)

如果要插入的值小于当前节点的值,应该插入到左子树;如果要插入的值大于当前节点的值,应该插入到右子树。

class Solution:
    # 插入值 val 到二叉搜索树中
    def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        
        # 如果当前节点为空,创建一个新的节点并返回
        if root is None or root.val == val:
            return TreeNode(val)  # 创建一个新的 TreeNode 节点,包含插入的值
        
        # 如果当前节点值大于 val,则应该将 val 插入到左子树
        elif root.val > val:
            # 如果左子树为空,直接插入该值作为左子节点
            if root.left is None:
                root.left = TreeNode(val)  # 创建一个新的节点,并赋值给左子节点
            else:
                # 如果左子树不为空,递归地在左子树中插入 val
                self.insertIntoBST(root.left, val)
        
        # 如果当前节点值小于 val,则应该将 val 插入到右子树
        elif root.val < val:
            # 如果右子树为空,直接插入该值作为右子节点
            if root.right is None:
                root.right = TreeNode(val)  # 创建一个新的节点,并赋值给右子节点
            else:
                # 如果右子树不为空,递归地在右子树中插入 val
                self.insertIntoBST(root.right, val)
        
        # 返回根节点,确保树的结构未被破坏
        return root

三、删除二叉搜索树中的节点(Leetcode 450)

删除节点的三种情况:

1、节点没有子节点(叶子节点):如果节点没有左子树也没有右子树(即叶子节点),直接删除该节点,返回 None,表示当前节点被删除。

2、节点只有右子树:如果节点没有左子树(root.left is None),那么可以用右子树代替当前节点。删除该节点并返回右子节点,实际上是把右子树提升为当前节点的子树。

3、节点只有左子树:如果节点没有右子树(root.right is None),那么可以用左子树代替当前节点。删除该节点并返回左子节点,实际上是把左子树提升为当前节点的子树。

4、节点有两个子树:从当前节点的右子树开始,递归找到右子树中最左的节点(cur.left is None),该节点就是右子树中的最小节点。将该最小节点的左子树指向当前节点的左子树。

返回右子树作为新树的根节点(也就是当前节点被删除,右子树的最小节点替代了它的位置)。

class Solution:
    # 删除二叉搜索树中的节点
    def deleteNode(self, root, key):
        # 如果当前节点为空,返回空
        # 表示没有找到节点或到达树的末端
        if root is None:
            return root

        # 如果当前节点的值等于要删除的值
        if root.val == key:
            # 如果节点没有子节点(叶子节点),直接删除该节点
            if root.left is None and root.right is None:
                return None
            
            # 如果节点只有右子树,直接返回右子树,删除当前节点
            elif root.left is None:
                return root.right
            
            # 如果节点只有左子树,直接返回左子树,删除当前节点
            elif root.right is None:
                return root.left
            
            # 如果节点有两个子树,找到右子树中的最小节点(左子树的最左节点)
            else:
                cur = root.right  # 从右子树开始
                # 寻找右子树中最小的节点(左子树最深的节点)
                while cur.left is not None:
                    cur = cur.left
                # 将右子树最小节点的左子树指向当前节点的左子树
                cur.left = root.left
                # 返回右子树作为新的根节点,替代当前节点
                return root.right
        
        # 如果当前节点的值大于要删除的值,递归到左子树中删除
        if root.val > key:
            root.left = self.deleteNode(root.left, key)
        
        # 如果当前节点的值小于要删除的值,递归到右子树中删除
        if root.val < key:
            root.right = self.deleteNode(root.right, key)
        
        # 返回根节点,确保树的结构未被破坏
        return root

相关文章:

  • Spring Boot 集成 RocketMQ 全流程指南:从依赖引入到消息收发
  • 【Three.js基础学习】35.Particles Cursor Animation Shader
  • 【笔记】对抗训练-GAN
  • 论文精度:双分支图Transformer网络:视频驱动的3D人体网格重建新突破
  • 记一次某网络安全比赛三阶段webserver应急响应解题过程
  • Spring Cloud主要组件介绍
  • 解密Oracle数据库RAC技术原理:构建高可用、可扩展的集群数据库
  • sward安装及入门指南
  • 揭秘大数据 | 20、软件定义数据中心
  • ELK+Filebeat 深度部署指南与实战测试全解析
  • MySQL聚合查询
  • 利用 限制torch线程数与异步方法提升声纹识别效率
  • 旧版 VMware 虚拟机迁移至 KVM 平台-案例2
  • 动手强化学习之马尔可夫决策(机器人篇)
  • keil如何创建一个工程
  • STM32单片机入门学习——第36节: [11-1] SPI通信协议
  • C++中extern关键字
  • 【微信开发者工具】解决微信开发工具的调试器加载错误,从任务栏打开工具可能导致该问题,请不要从任务栏启动工具
  • Redis 常问知识
  • MCP的另一面
  • 教育部召开全国中小学幼儿园安全工作视频会议:加强校园安防建设
  • 被指违反代理协议遭南航暂停售票资格, 去哪儿网:今起恢复
  • 田野调查|“心青年”的日常秩序与归属之地
  • 白宫慌了!将设工作组紧急处理对中国加征关税危机
  • 九部门:将符合条件的家政从业人员纳入公租房等保障范围
  • 商务部:中方愿与欧方共同努力,维护多边贸易体制