代码随想录算法训练营第二十二天| LeetCode235. 二叉搜索树的最近公共祖先、LeetCode701. 二叉搜索树中的插入操作、LeetCode450. 删除二叉搜索树中的节点

一、LeetCode235. 二叉搜索树的最近公共祖先

        1:题目描述(235. 二叉搜索树的最近公共祖先)

        给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

        百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

        例如,给定如下二叉搜索树:  root = [6,2,8,0,4,7,9,null,null,3,5]

代码随想录算法训练营第二十二天| LeetCode235. 二叉搜索树的最近公共祖先、LeetCode701. 二叉搜索树中的插入操作、LeetCode450. 删除二叉搜索树中的节点_第1张图片

       代码随想录算法训练营第二十二天| LeetCode235. 二叉搜索树的最近公共祖先、LeetCode701. 二叉搜索树中的插入操作、LeetCode450. 删除二叉搜索树中的节点_第2张图片

        2:解题思路

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        # 自己的写法
        # # 找到了节点p、或q
        # if root == p or root == q:
        #     print(root)
        #     return root

        # # 向左遍历
        # if root.val > p.val or root.val > q.val:
        #     print(1)
        #     left = self.lowestCommonAncestor(root.left, p, q)
        # else:
        #     left = None
        # if root.val < p.val or root.val < q.val:
        #     print(2)
        #     right = self.lowestCommonAncestor(root.right, p, q)
        # else:
        #     right = None

        # 在二叉搜索树中寻找最近的公共祖先
        # 如果当前节点的值,大于p、q节点的值,说明最近公共祖先在左子树中
        # 如果当前节点的值,小于p、q节点的值,说明最近公共祖先在右子树中
        # 如果当前节点的值,介于p、q节点值中间,说明p、q一个在当前节点的左子树中,一个在右子树中,即当前节点就是p、q的最近公共祖先
        
        # # 递归
        # if root == None:
        #     return None
        # if root.val > p.val and root.val > q.val:
        #     # 用left记录左子树中返回的公共祖先节点
        #     left = self.lowestCommonAncestor(root.left, p, q)
        #     # left不为空,就直接将公共祖先的节点向上返回
        #     if left != None:
        #         return left
        # if root.val < p.val and root.val < q.val:
        #     right = self.lowestCommonAncestor(root.right, p, q)
        #     if right != None:
        #         return right
        # # 当前节点的值,介于p、q之间,就直接返回当前节点
        # return root

        # 迭代
        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

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

        1:题目描述(701. 二叉搜索树中的插入操作)

        给定二叉搜索树(BST)的根节点 root 和要插入树中的值 value ,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。

        注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果 。

代码随想录算法训练营第二十二天| LeetCode235. 二叉搜索树的最近公共祖先、LeetCode701. 二叉搜索树中的插入操作、LeetCode450. 删除二叉搜索树中的节点_第3张图片

代码随想录算法训练营第二十二天| LeetCode235. 二叉搜索树的最近公共祖先、LeetCode701. 二叉搜索树中的插入操作、LeetCode450. 删除二叉搜索树中的节点_第4张图片

        2:解题思路

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        # 递归-自己的写法
        # if root == None:
        #     # 当根节点为空,就将值为val的节点作为根节点
        #     new_node = TreeNode(val)
        #     root = new_node
        # # 当前节点的值大于val,val应该插入当前节点的左子树中
        # if root.val > val:
        #     # 当前节点的左子树不为空,继续向左遍历
        #     if root.left:
        #         self.insertIntoBST(root.left, val)
        #     # # 当前节点的左节点为空,就将值为val的节点插入当前节点的左节点
        #     else:
        #         new_node = TreeNode(val)
        #         root.left = new_node
        # # 当前节点的值小于val,val应该插入当前节点的右子树中
        # if root.val < val:
        #     if root.right:
        #         self.insertIntoBST(root.right, val)
        #     else:
        #         new_node = TreeNode(val)
        #         root.right = new_node
        # return root

        # 递归-代码随想录
        # if root == None:
        #     # 当当前节点为空时,将值val定义为一个新节点,向上返回这个新节点
        #     new_node = TreeNode(val)
        #     return new_node
        # if root.val > val:
        #     # 当前节点的值,大于val,说明要在当前节点的左子树中插入这个节点
        #     # 因为当节点为空时,向上返回了新节点,所以需要有一个变量来接收这个值
        #     root.left = self.insertIntoBST(root.left, val)
        # if root.val < val:
        #     # 当前节点的值,小于val,说明要在当前节点的右子树中插入这个节点
        #     # 因为当节点为空时,向上返回了新节点,所以需要有一个变量来接收这个值
        #     root.right = self.insertIntoBST(root.right, val)
        # return root

        # 迭代法
        new_node = TreeNode(val)
        cur = root
        if not root:
            root = new_node
        while cur:
            if cur.val > val:
                if cur.left:
                    cur = cur.left
                else:
                    cur.left = new_node
                    break
            if cur.val < val:
                if cur.right:
                    cur = cur.right
                else:
                    cur.right = new_node
                    break
        return root

三、LeetCode450. 删除二叉搜索树中的节点

        1:题目描述(450. 删除二叉搜索树中的节点)

        给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。

        一般来说,删除节点可分为两个步骤:

  • 首先找到需要删除的节点;
  • 如果找到了,删除它。

代码随想录算法训练营第二十二天| LeetCode235. 二叉搜索树的最近公共祖先、LeetCode701. 二叉搜索树中的插入操作、LeetCode450. 删除二叉搜索树中的节点_第5张图片代码随想录算法训练营第二十二天| LeetCode235. 二叉搜索树的最近公共祖先、LeetCode701. 二叉搜索树中的插入操作、LeetCode450. 删除二叉搜索树中的节点_第6张图片        2:解题思路

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]:
        # 当节点为空,没有要删除的节点,则直接返回None
        if root == None:
            return None
        # 当当前节点就是需要删除的节点,有以下四种情况
        if root.val == key:
            # 第一种:当前节点为叶子节点,左右子节点都为空
            if root.left == None and root.right == None:
                # 直接将空返回给上层节点,就可以将当前节点删除
                return None
            # 第二种:当前节点的左节点不为空,右节点为空
            elif root.left != None and root.right == None:
                # 直接将当前节点的左节点返回给上层,就可以将当前节点删除
                return root.left
            # 第三种:当前节点的左节点为空,右节点不为空
            elif root.left == None and root.right != None:
                # 直接将当前节点的右节点返回给上层,就可以将当前节点删除
                return root.right
            # 第四种:当前节点的左右子节点均不为空,此时需要更改二叉树的结构
            else:
                # # 第一种方式:
                # # 将当前节点的右节点,做为当前节点的左右子树的父节点
                # # 需要将当前节点的左子树,添加到当前节点的右节点的左子树中的最左下角的位置
                # # 定义一个临时指针,指向当前节点的右节点
                # cur = root.right
                # # 循环遍历到当前节点右子树的最左侧节点
                # while cur.left:
                #     # 遍历的左节点一直不为空,就一直向下遍历
                #     cur = cur.left
                # # cur.left为空的时候,将当前节点的左子树赋值给cur.left
                # cur.left = root.left
                # # 返回当前节点的右节点
                # return root.right

                # 第二种方式
                # 将当前节点的左节点,作为当前节点的左右子树的父节点
                # 就需要将当前节点的右子树,添加到当前节点的左节点的右子树的最右下角的位置
                cur = root.left
                while cur.right:
                    cur = cur.right
                cur.right = root.right
                return root.left
        # 当当前节点的值大于key时,向左子树遍历
        if root.val > key:
            root.left = self.deleteNode(root.left, key)
        # 当当前节点的值小于key时,向右子树遍历
        if root.val < key:
            root.right = self.deleteNode(root.right, key)
        return root

你可能感兴趣的:(算法训练营(LeetCode),算法,python,leetcode,二叉树)