leetcode—23.二叉搜索树题目leetcode总结

基本操作类题目

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

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

示例:

输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
输出: 6
解释: 节点 2 和节点 8 的最近公共祖先是 6。
在这里插入图片描述

按照最近公共祖先的定义,我们可以知道p、q、root为下面三种情况之一:

  1. p、q在root的左右子树中
  2. p = root,q在root的左右子树中
  3. q = root,p在root的左右子树中

思路1:迭代搜索

  • 当节点root为空时跳出;
  • 当p,q都在root的右子树中,则遍历至root.right ;否则,当p,q都在root的左子树中,则遍历至root.left;否则,说明找到了最近公共祖先,跳出。

返回值:最近公共祖先root 。

# 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':
        cur_node = root
        # 迭代循环搜索
        while cur_node:
            # 如果p,q都在左子树中
            if p.val < cur_node.val and q.val < cur_node.val:
                cur_node = cur_node.left
            # 如果p,q都在右子树中
            elif p.val > cur_node.val and q.val > cur_node.val:
                cur_node = cur_node.right
            # 如果p,q分别在左子树与右子树中,则返回当前节点
            else:
                return cur_node

思路2:递归

  • 当p,q都在root的右子树中,则开启递归root.right并返回;否则,
  • 当p,q都在root的左子树中,则开启递归root.left 并返回;

返回值:最近公共祖先 root。

# 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':
        # 递归
        if p.val > root.val and q.val > root.val:
            return self.lowestCommonAncestor(root.right,p,q)
        elif p.val < root.val and q.val < root.val:
            return self.lowestCommonAncestor(root.left,p,q)
        else:
            return root

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

给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
一般来说,删除节点可分为两个步骤:
首先找到需要删除的节点;
如果找到了,删除它。
说明: 要求算法时间复杂度为 O(h),h 为树的高度。

示例:
在这里插入图片描述

思路:

理解这个算法的关键在于保持BST中序遍历的顺序性
删除一个节点会有三种情况:

  1. 待删除的节点左子树为空,此时,让待删除节点的右子树代替它即可
  2. 待删除的节点右子树为空,此时,让待删除节点的左子树代替它即可
  3. 待删除节点的左右子树都不为空,则可以有两种处理方式:
    1. 让待删除节点的前驱结点带她它
      在这里插入图片描述
      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: TreeNode, key: int) -> TreeNode:
        # 如果根节点为空,返回None
        if root == None:
            return root

        # 递归调用左子树,寻找等于key的值
        if key < root.val:
            root.left = self.deleteNode(root.left,key)
            return root

        # 递归调用右子树,寻找等于key的值
        if key > root.val:
            root.right = self.deleteNode(root.right,key)
            return root

        # 删除一个节点会有三种情况:
        # 1.待删除的节点左子树为空,让待删除节点的右子树代替它即可
        if root.left == None:
            new_root = root.right
            root.right = None
            return new_root

        # 2.待删除的节点右子树为空,让待删除节点的左子树代替它即可
        if root.right == None:
            new_root = root.left
            root.left = None
            return new_root

        # 3. 待删除节点的左右子树都不为空,让待删除节点的前驱结点代替它
        node = root.left
        # 找到前驱结点
        while node.right != None:
            node = node.right
        # 将前驱节点变为新的根节点
        new_root = TreeNode(node.val)
        # 前驱节点的左子树进行更新,因为左子树删除了前驱结点
        new_root.left = self.removeMax(root.left)
        # 新的根节点的右子树不用更新
        new_root.right = root.right

        # 将删除的根节点的引用去掉
        root.left = None
        root.right = None
        return new_root

    def removeMax(self,node):
        if node.right == None:
            new_root = node.left
            node.left = None
            return new_root
        # 如果右节点不为空,则递归寻找最右节点
        node.right = self.removeMax(node.right)
        
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值