day20 代码随想录 | 二叉搜索树的插入 二叉搜索树的删除 二叉搜索树的最近公共祖先

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

这个题和二叉树的最近公共祖先很像,你也可像二叉树那样去做,但是就是没有用到二叉树的性质

二叉树的性质可以用来完成剪枝的操作。

二叉树搜索树就是,你可以找左边和找右边,根据p,q的value的大小

如果 p,q 都小于key的value, 那么就走root.left 都大于,走root.right。否则,就改返回了 此时的root就是该节点。

递归

def dfs(root, p, q):
    if not root: return None

    if root.val > p.val and root.val > q.val:
        left = dfs(root.left, p, q)
        if left is not None:
            return left
    
    if root.val < p.val and root.val < q.val:
        right = dfs(root.right, p, q)
        if right is not None:
            return right

    return root

迭代法,这个题也可以用迭代,因为有序数组。

思路一样

def lowestCommonAncestor(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:
            reutrn root

    return None

二叉搜索树的插入

其实这个题很简单,你模拟就知道,你插入的节点必然是叶子节点,对叶子节点进行操作。

这个题可以递归和迭代的思路,因为二叉搜索树是有序的。

我们先用迭代的思路,这个很好理解

当root.val > val root = root.left

root.val < val root = root.right

什么时候停止呢? 因为这个插入的节点是不相等的。一个简单的想法就是while cur is not None.

但是当他走到叶子节点的时候,他还会继续往下走,cur.left 就是None。那其实我们需要保存一个cur节点用一个变量parent,让parent去操作!

迭代法

def insertBST(root, key):
    node = TreeNode(key)
    if not root:
        return node
    cur = root
    parent = root
    while cur:
        parent = cur
        if cur.val > key:
            cur = cur.left
        else:
            cur = cur.right
    if parent.cur > key:
        parent.left = node
    else:
        parent.right = node

    return root

递归法

class Solution:

    def dfs(self, root, val):
        if (root == None):
            node = TreeNode(val)
            return node

        if (root.val > val) root.left = self.dfs(root.left, val)

        if (root.val < val) root.right = self.dfs(root.right, val)

        return root
            

二叉搜索树的删除

二叉搜索树的删除要考虑很多情况

同样递归三部曲

1. 递归函数的参数和返回值:参数就是root 和key 

2. 中止条件:如果遇到是空 就返回root

3. 确认单层递归,分情况讨论

1. 没找到删除删除的节点,遇到空节点就直接返回了

2.找到删除的节点

   1. 如果是叶子节点,那么直接删除节点,返回null为根节点

    2.  删除节点左孩子不为空,右孩子为空,删除该节点,右孩子补位

   3. 删除节点左孩子为空,右孩子不为空,删除该节点,左孩子补位

   4. 删除节点左右孩子都不为空。那么就要找到右子树最左边的叶子节点,然后将该头节点的左子树凭借到删除节点右子树的最左边的孩子上。如下图所示【图片来源于代码随想录】 

假设要删除的元素是7

将7的左子树放在7的右子树左边的节点

将7节点删除,右子树为新的点

代码如下

class Solution:
    def deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]:
        
        if not root: return None

        if root.val == key:

            if root.left is None and root.right is None:
                return None
            
            elif root.left is None and root.right is not None:
                return root.right

            elif root.left is not None and 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
            

            

            

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值