代码随想录算法训练营|Day 20

Day 20

第六章 二叉树part07

235. 二叉搜索树的最近公共祖先

相对于 二叉树的最近公共祖先 本题就简单一些了,因为 可以利用二叉搜索树的特性

题目链接/文章讲解:https://programmercarl.com/0235.二叉搜索树的最近公共祖先.html
视频讲解:https://www.bilibili.com/video/BV1Zt4y1F7ww

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        if min(p.val, q.val) < root.val < max(p.val,q.val) or root.val == min(p.val,q.val) or root.val == max(p.val,q.val):
            return root
        else:
            return self.lowestCommonAncestor(root.left if max(p.val,q.val) < root.val else root.right, p, q)

从上向下去递归遍历,第一次遇到 cur节点是数值在[q, p]区间中,那么cur就是 q和p的最近公共祖先。

思路:对于BST, 若p/q均大于cur.val,那么向右子树搜索;若p/q均小于cur.val,那么向左子树搜索

若cur.val在p/q之间,则cur本身是最近公共祖先

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        if p.val > root.val and q.val > root.val:
            right = self.lowestCommonAncestor(root.right, p, q)
        elif p.val < root.val and q.val < root.val:
            left = self.lowestCommonAncestor(root.left, p, q)
        else:
            return root

迭代法

class Solution:
    def lowestCommonAncestor(self, root, p, q):
        while root:
            if root.val > p.val and root.val > q.val:
                root = root.left
            elif root.val < p.val and root.val < q.val:
                root = root.right
            else:
                return root
        return None

701.二叉搜索树中的插入操作

本题比想象中的简单,大家可以先自己想一想应该怎么做,然后看视频讲解,就发现 本题为什么比较简单了。

题目链接/文章讲解:https://programmercarl.com/0701.二叉搜索树中的插入操作.html
视频讲解:https://www.bilibili.com/video/BV1Et4y1c78Y

递归法

class Solution:
    def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        if not root:
            return TreeNode(val)
        if root.val > val:
            root.left = self.insertIntoBST(root.left, val)
        elif root.val < val:
            root.right = self.insertIntoBST(root.right, val)
        return root

迭代法

class Solution:
    def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        if not root: # 如果根节点为空,创建新节点作为根节点并返回
            return TreeNode(val)
        cur = root
        while cur:
            if val < cur.val:
                if not cur.left: # 如果此时父节点的左子树为空
                    cur.left = TreeNode(val) # 将新节点连接到父节点的左子树
                    return root
                else:
                    cur = cur.left
            elif val > cur.val:
                if not cur.right: # 如果此时父节点的左子树为空
                    cur.right = TreeNode(val) # 将新节点连接到父节点的右子树
                    return root
                else:
                    cur = cur.right

450.删除二叉搜索树中的节点

相对于 插入操作,本题就有难度了,涉及到改树的结构

题目链接/文章讲解:https://programmercarl.com/0450.删除二叉搜索树中的节点.html
视频讲解:https://www.bilibili.com/video/BV1tP41177us

下面这种是取代的方法
当要删除的节点有左右孩子,用左子树的最大值or右子树的最小值去取代节点本身,再删除我们选择的那个最大值or最小值

class Solution:
    def deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]:
        if not root:
            return root
        if root.val > key:
            root.left = self.deleteNode(root.left,key)
        elif root.val < key:
            root.right = self.deleteNode(root.right, key)
        else:
            if not root.right:
                return root.left
            elif not root.left:
                return root.right
            else:
                minNode = self.findMin(root.right)
                root.val = minNode.val
                root.right = self.deleteNode(root.right, minNode.val)
        return root
    def findMin(self, root):
        curr = root
        while curr.left:
            curr = curr.left
        return curr

情况:

  • 没找到需要删除的节点

  • 找到了节点

    • 删的点是叶子节点
    • 删的点非叶子节点
      • 左为空,右不为空 ->父节点指向右孩子
      • 左不为空,右为空 ->父节点指向左孩子
      • 左右都不为空 -> 左子树成为右子树最小的左孩子,父节点指向右子树

递归法

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
                #返回修正好的树
                #修正好的树直接没有值等于key的根节点了
                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

递归法

class Solution:
    def deleteNode(self, root, key):
        if root is None:  # 如果根节点为空,直接返回
            return root
        if root.val == key:  # 找到要删除的节点
            #包含的情况:
            #1. 左右子树都为空
            #2. 左子树不为空,右为空
            if root.right is None:  # 如果右子树为空,直接返回左子树作为新的根节点
                return root.left

            #3.左为空,右不空
            #4.左右都不空
            cur = root.right
            while cur.left:  # 找到右子树中的最左节点
                cur = cur.left
            root.val, cur.val = cur.val, root.val  # 将要删除的节点值与最左节点值交换
        root.left = self.deleteNode(root.left, key)  # 在左子树中递归删除目标节点
        root.right = self.deleteNode(root.right, key)  # 在右子树中递归删除目标节点
        return root

不想看迭代法了但是存一个

迭代法

class Solution:
    def deleteOneNode(self, target: TreeNode) -> TreeNode:
        """
        将目标节点(删除节点)的左子树放到目标节点的右子树的最左面节点的左孩子位置上
        并返回目标节点右孩子为新的根节点
        是动画里模拟的过程
        """
        if target is None:
            return target
        if target.right is None:
            return target.left
        cur = target.right
        while cur.left:
            cur = cur.left
        cur.left = target.left
        return target.right

    def deleteNode(self, root: TreeNode, key: int) -> TreeNode:
        if root is None:
            return root
        cur = root
        pre = None  # 记录cur的父节点,用来删除cur
        while cur:
            if cur.val == key:
                break
            pre = cur
            if cur.val > key:
                cur = cur.left
            else:
                cur = cur.right
        if pre is None:  # 如果搜索树只有头结点
            return self.deleteOneNode(cur)
        # pre 要知道是删左孩子还是右孩子
        if pre.left and pre.left.val == key:
            pre.left = self.deleteOneNode(cur)
        if pre.right and pre.right.val == key:
            pre.right = self.deleteOneNode(cur)
        return root
posted @ 2025-08-25 18:27  ForeverEver333  阅读(11)  评论(0)    收藏  举报