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

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

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

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

自己做

思路:

二叉搜索树和普通的二叉树在处理最近公共祖先的问题上有什么不同?
利用二叉搜索树的特性:

  1. 如果根结点等于q或者q,那么直接返回根结点

  2. 如果q和p在跟根结点的两侧,那么也是直接返回根结点

  3. 如果q和p在根结点的同侧,那么进入到所在侧,进入所在侧以后,重复1,2,3步->有返回值的,返回单条路径的递归

代码:

python

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

class Solution(object):
    def lowestCommonAncestor(self, root, p, q):
        """
        :type root: TreeNode
        :type p: TreeNode
        :type q: TreeNode
        :rtype: TreeNode
        """
        # 二叉搜索树和普通的二叉树在处理最近公共祖先的问题上有什么不同?
        # 
        '''
        利用二叉搜索树的特性:
        1. 如果根结点等于q或者q,那么直接返回根结点
        2. 如果q和p在跟根结点的两侧,那么也是直接返回根结点
        3. 如果q和p在根结点的同侧,那么进入到所在侧,进入所在侧以后,重复1,2,3步->有返回值的,返回单条路径的递归
        '''
        # 在根结点
        #print(root.left.val, p.val, q.val)
        if root.val == q.val or root.val == p.val:
            #print(1)
            return root
        
        # 在两边
        if (root.val > p.val and root.val < q.val) or (root.val > q.val and root.val < p.val):
            #print(2)
            return root


        # 3. 单层递归逻辑
        if root.val > p.val and root.val > q.val:
            # 都在左侧
            #print(3)
            #print(root.left.val)
            #print(root.left.val, p.val, q.val)
            return self.lowestCommonAncestor(root.left, p, q)
        elif root.val < p.val and root.val < q.val:
            # 都在右侧
            #print(5)
            return self.lowestCommonAncestor(root.right, p, q)

        #print(5)

代码随想录

思路:

只要从上到下去遍历,遇到 cur节点是数值在[p, q]区间中则一定可以说明该节点cur就是q 和 p的公共祖先

代码:

python

class Solution:
    def traversal(self, cur, p, q):
        if cur is None:
            return cur
                                                        # 中
        if cur.val > p.val and cur.val > q.val:           # 左
            left = self.traversal(cur.left, p, q)
            if left is not None:
                return left

        if cur.val < p.val and cur.val < q.val:           # 右
            right = self.traversal(cur.right, p, q)
            if right is not None:
                return right

        return cur # 都不满足那就是在中间了!!!

    def lowestCommonAncestor(self, root, p, q):
        return self.traversal(root, p, q)

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

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

自己做

思路:

见代码,唯一需要注意的是需要在向下搜索的过程中需要有一个判断

代码:

python

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def insertIntoBST(self, root, val):
        """
        :type root: TreeNode
        :type val: int
        :rtype: TreeNode
        """
        if root == None:
            root = TreeNode(val)
            return root

        if root.val < val:
            if root.right != None:
                self.insertIntoBST(root.right, val)
            if root.right == None:
                cur = TreeNode(val)
                root.right = cur
                
        if root.val > val:
            if root.left != None:
                self.insertIntoBST(root.left, val)
            if root.left == None:
                cur = TreeNode(val)
                root.left = cur
            
        return root

代码随想录

思路:

搜索树是有方向了,可以根据插入元素的数值,决定递归方向。

代码:

python

class Solution:
    def insertIntoBST(self, root, val):
        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

到这里,大家应该能感受到,如何通过递归函数返回值完成了新加入节点的父子关系赋值操作了,下一层将加入节点返回,本层用root->left或者root->right将其接住。

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

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

思路:

难点在于:

找到了结点如何删除并保证删除之后的树还是二叉搜索树

我的思路

分情况讨论:

  1. 如果是叶子结点->直接删除

  2. 如果只有左子树->用左子树最右侧结点替换

  3. 如果只有右子树->用右子树最左面结点替换

  4. 如果既有左子树又有右子树->用左子树最右侧结点替换或用左子树最右侧结点替换

第四种情况的理解是错误的,有些情况处理不了

在这里插入图片描述
左子树最右侧结点和左子树最右侧结点 都不存在 这时替换会破坏整个树的结构

最终代码没有实现,下面的代码是自己按照答案自己写的

代码:

python


代码随想录

思路:

递归三部曲

  1. 确定递归函数参数以及返回值

    def deleteNone(self, root, key)

  2. 确定终止条件:遇到空返回,其实这也说明没找到删除的节点,遍历到空节点直接返回了

    if root == None: return root # 1.

  3. 确定单层递归的逻辑

有以下五种情况:

  • 第一种情况:没找到删除的节点,遍历到空节点直接返回了

  • 找到删除的节点

    • 第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点

    • 第三种情况:删除节点的左孩子为空,右孩子不为空,删除节点,右孩子补位,返回右孩子为根节点

    • 第四种情况:删除节点的右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点

    • 第五种情况:左右孩子节点都不为空,则将删除节点的左子树头结点(左孩子)放到删除节点的右子树的最左面节点的左孩子上,返回删除节点右孩子为新的根节点。

    if root.val == key:
    	# 2.
    	if not root.left and not root.right:
    		return None
    	# 3.
    	if not root.left and root.right:
    		# 右孩子补位
    		return root.right
    	# 4.
    	if root.left and not root.right:
    		# 左孩子补位
    		return root.left
    	# 5.
    	if root.left and root.right:
    		cur = root.right
    		while cur.left != None:
    			cur = cur.left
    		cur.left = root.left
    		return root.right	
    
    if root.val < key: root.right = self.deleteNone(root.right, key)
    if root.val > key: root.left = self.deleteNone(root.left, key)
    

代码:

python

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def deleteNode(self, root, key):
        """
        :type root: TreeNode
        :type key: int
        :rtype: TreeNode
        """
        if root == None: return root # 1.

        if root.val == key:
		    # 2.
            if not root.left and not root.right:
                return None
            # 3.
            if not root.left and root.right:
                # 右孩子补位
                return root.right
            # 4.
            if root.left and not root.right:
                # 左孩子补位
                return root.left
            # 5.
            if root.left and root.right:
                cur = root.right
                while cur.left != None:
                    cur = cur.left
                cur.left = root.left
                return root.right	


        if root.val < key: 
            root.right = self.deleteNode(root.right, key)
        if root.val > key: 
            root.left = self.deleteNode(root.left, key)
        return root
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值