代码随想录 Day 20 | 【第六章 二叉树part07】235. 二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点

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

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

1. 找最近祖先

        (1)根据二叉搜索树的特性,中间节点一定大于其左子树所有值,一定小于右子树所有值。所以首先判断中间节点和p、q二者之间的大小,如果均大于中间节点,说明一定都在其右子树;反之,则都在左子树;如果一大一小,则在左右子树上。

        (2)如何判断是最近的祖先而不是次近的:如果继续向下遍历,p或q有一个消失的话,说明错过p或q,不能继续向下遍历了,当前的中间节点就是最近的祖先。

2. 代码实现

(1)定义递归函数,传入的是当前遍历的节点、p和q,返回值是节点。

(2)确定终止条件:首先本题不需要前中后序,只需要左和右即可,中间节点无需处理。

        1)如果当前节点的值大于p的值且大于q的值,说明p和q均在左子树上,所以向左去遍历搜索。终止条件就是当左为空,就返回节点。

        2)如果当前节点的值小于p的值且小于q的值,说明p和q均在右子树上,所以向右去遍历搜索。终止条件就是当右为空,就返回节点。

(3)剩下的情况就是节点在p和q之间,不需要去管谁大谁小,直接返回当前节点即可。

# 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 root is None or root == p or root == q: 
            return root

        # left:
        if root.val > p.val and root.val > q.val:
            left = self.lowestCommonAncestor(root.left, p, q)
            if left is not None: 
                return left

        # right:
        if root.val < p.val and root.val < q.val:
            right = self.lowestCommonAncestor(root.right, p, q)
            if right is not None: 
                return right

        return root

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

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

1. 解题思路

        根据探究可以发现,任何一个要插入的节点都可以最终在某个叶子节点后插入,无需改变这颗二叉树的原始结构,这种做法是最简单的。

        注意:如果问题将二叉搜索树变成平衡二叉树,那么超过一定深度就需要改变树的结构。

(1)确定递归函数的参数和返回值:递归函数的参数为传入的二叉树根节点和需要插入节点的值,返回值是改变后的二叉树根节点。

(2)确定终止条件:

        递归遇到空,就终止递归,同时也找到了我们需要插入新节点的位置;所以定义一个新节点,传入数值,然后将这个新节点返回给上一个节点。

(3)如果当前节点的值大于新节点的值,那么向左去遍历,最后用root.left接住这个节点。 

(4)如果当前节点的值小于新节点的值,那么向右去遍历,最后用root.right接住这个节点。

(5)最后返回root即可。

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 is None:
            node = TreeNode(val)
            return node

        if root.val > val:
            root.left = self.insertIntoBST(root.left, val)
        if root.val < val:
            root.right = self.insertIntoBST(root.right, val)

        return root

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

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

1. 分析五种情况

所需删除的节点位置一共分以下五种情况: 

(1)左子树和右子树均为空:说明需要删除的是叶子节点

(2)左子树为空和右子树不为空:直接将右子树的父节点改成待删除的节点的父节点

(3)右子树为空和左子树不为空:直接将左子树的父节点改成待删除的节点的父节点

(4)左子树和右子树均不为空:根据二叉搜索树的特性,将左子树的最大值(即左子树的根节点)连接到右子树的最小值(即右子树最左侧的叶子节点)下面。

(5)没找到需要删除的根节点。

2. 代码实现

(1)定义递归函数的参数和返回值:传入参数二叉搜索树根节点,以及需要删除的节点值,返回的是更新后的二叉树根节点。

(2)确定终止条件:即找到需要删除的节点值就终止递归,进行删除操作。

        1)没有找到待删除节点/该二叉树为空:返回null。

        2)找到待删除节点:

                A. 如果待删除节点为叶子节点:即左右子树均为空,那么进行删除节点操作,直接返回null,也就是将null返回给了叶子节点的父节点。

                B. 如果待删除节点左不为空而右为空:返回左子树,也就是将左子树返回给了待删除节点的父节点。

                C. 如果待删除节点左为空而右不为空:返回左子树,也就是将右子树返回给了待删除节点的父节点。

                D. 如果待删除节点左右均不为空:即需要将左子树的根节点移动到右子树的最左侧的叶子节点下面。a. 首先定义cur指针指向待删除节点,然后对右子树一直进行向左遍历,直到来到其最左侧的叶子节点; b.然后将待删除节点的左子树移动到该叶子节点;c.删除待删除节点:让待删除节点的父节点直接指向右子树的根节点即可,在此处我们直接返回右子树给父节点。

(3)单层递归逻辑:

        1)根据二叉搜索树的特性,如果root.val大于key,那么直接向左递归,注意递归函数有返回值,所以需要root.left接住;

        2)根据二叉搜索树的特性,如果root.val小于key,那么直接向右递归,注意递归函数有返回值,所以需要root.right接住;

(4)最后返回root。

# 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]:
        # 确定递归的终止条件——找到待删除节点:
        if root is None:
            return None

        if root.val == key:
            # 待删除节点是叶子节点:
            if root.left is None and root.right is None:
                return None
            elif root.left is not None and root.right is None:
                return root.left
            elif root.left is None and root.right is not None:
                return root.right
            else: # 待删除节点左右子树均不为空
                cur = root.right
                while cur.left:
                    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
                

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值