【二叉树】刷题二(以递归写法为主)

在这里插入图片描述

617. 合并二叉树

在这里插入图片描述

class Solution:
    def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
        root = TreeNode()
        if not root1 and not root2:
            return
        elif root1 and not root2:
            root = root1
        elif not root1 and root2:
            root = root2
        elif root1 and root2:
            root.val = root1.val + root2.val
            root.left = self.mergeTrees(root1.left, root2.left)
            root.right  = self.mergeTrees(root1.right,root2.right)
        return root

700.二叉搜索树中的搜索

在这里插入图片描述

class Solution:
    def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        if not root or root.val==val:
            return root
        if root.val<val:
            return self.searchBST(root.right,val)
        elif root.val>val:
            return self.searchBST(root.left,val)

98.验证二叉搜索树

在这里插入图片描述

class Solution:
    def __init__(self):
        self.valid = float('-inf')
    def isValidBST(self, root: Optional[TreeNode]) -> bool:
        # 中序遍历的结果一定是从小到大,否则为false
        if not root:
            return True
        left = self.isValidBST(root.left)
        if self.valid<root.val:
            self.valid = root.val
        else:
            return False
        right = self.isValidBST(root.right)
        return left and right

530.二叉搜索树的最小绝对差

在这里插入图片描述

class Solution:
    def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
        # 先中序遍历,在找到差值最小的两个值之间。因为二插搜索树的中序遍历是从小到大,所以两两找就可以找到差值最小值了。
        res = []
        def dfs(root):
            if not root:
                return 
            dfs(root.left)
            res.append(root.val)
            dfs(root.right)
        dfs(root)
        min_value = res[-1]
        for i in range(len(res)-1):
            min_value = min(min_value,res[i+1]-res[i])
        return min_value

501.二叉搜索树中的众数

在这里插入图片描述

class Solution:
    def findMode(self, root: Optional[TreeNode]) -> List[int]:
        # 先中序遍历,在按照counter的次数进行排序,返回计数最大的几个值。
        res = []
        def dfs(root):
            if not root:
                return 
            dfs(root.left)
            res.append(root.val)
            dfs(root.right)
        dfs(root)
        final_statics = collections.Counter(res)
        sorted_value = sorted(final_statics.items(),key=lambda x:x[-1],reverse = True)
        res = []
        for key,value in sorted_value:
            if value == sorted_value[0][1]:
                res.append(key)
        return res

236. 二叉树的最近公共祖先

在这里插入图片描述
详细看代码随想录中本题题解
思路:

  • 求最小公共祖先,需要从底向上遍历,那么二叉树,只能通过后序遍历(即:回溯)实现从底向上的遍历方式。
  • 在回溯的过程中,必然要遍历整棵二叉树,即使已经找到结果了,依然要把其他节点遍历完,因为要使用递归函数的返回值(也就是代码中的left和right)做逻辑判断。
  • 要理解如果返回值left为空,right不为空为什么要返回right,为什么可以用返回right传给上一层结果。

如果找到一个节点,发现左子树出现结点p,右子树出现节点q,或者 左子树出现结点q,右子树出现节点p,那么该节点就是节点p和q的最近公共祖先。
在这里插入图片描述

在这里插入图片描述
递归三部曲:
1、确定递归函数返回值以及参数

lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':

2、确定终止条件
遇到空的话,因为树都是空了,所以返回空。
那么我们来说一说,如果 root == q,或者 root == p,说明找到 q p ,则将其返回,这个返回值,后面在中节点的处理过程中会用到,那么中节点的处理逻辑,下面讲解。

if (root == q || root == p || root == NULL) return root;

3、确定单层递归逻辑 (是遍历一边?还是遍历整颗树?)

PS:
在这里插入图片描述
本题中,在递归函数有返回值的情况下:如果要搜索一条边,递归函数返回值不为空的时候,立刻返回,如果搜索整个树,直接用一个变量left、right接住返回值,这个left、right后序还有逻辑处理的需要,也就是后序遍历中处理中间节点的逻辑(也是回溯)。

在这里插入图片描述
如果left 和 right都不为空,说明此时root就是最近公共节点。这个比较好理解
如果left为空,right不为空,就返回right,说明目标节点是通过right返回的,反之依然。


class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':

        if p==root or  q==root or not root:  # 要么返回p,要么返回q,要么返回空。
            return root
        left = self.lowestCommonAncestor(root.left,p,q)
        right = self.lowestCommonAncestor(root.right,p,q)
        if left and not right:
            return left    # 如果左存在,右与空,则说明左侧中包含p/q,先找到的本身就是最近祖先
        if right and not left:
            return right   # 如果左为空,右存在,则说明右侧中包含p/q,先找到的本身就是最近祖先
        if left and right:
            return root   # 这里注意返回的是root,也就是祖先,而不是返回left/right

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

在这里插入图片描述
在这里插入图片描述

class Solution:
    def deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]:
        if not root:    # 没找到删除的节点,遍历到空节点直接返回了
            return root 
        if root.val == key:  # 找到删除的节点
            if root.right and not root.left:   # 删除节点的左孩子为空,右孩子不为空,删除节点,右孩子补位,返回右孩子为根节点
                return root.right
            elif root.left and not root.right: # 删除节点的右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点
                return root.left
            elif root.left and root.right:   # 既有左孩子,也有由孩子的情况
                cur = root.right
                while cur.left is not None:   # 找到右子树最左下角的一个
                    cur = cur.left
                cur.left = root.left
                return root.right
            else:          # 左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点
                return None

        if root.val>key: # left
            root.left = self.deleteNode(root.left,key)
        if root.val<key:
            root.right = self.deleteNode(root.right,key)
        return root

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

在这里插入图片描述

class Solution:
    def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
       

        if not root:
            subTree = TreeNode(val = val)
            return subTree
        
        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.删除二叉搜索树中的节点

在这里插入图片描述
在这里插入图片描述

class Solution:
    def deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]:
        if not root:    # 没找到删除的节点,遍历到空节点直接返回了
            return root 
        if root.val == key:  # 找到删除的节点
            if root.right and not root.left:   # 删除节点的左孩子为空,右孩子不为空,删除节点,右孩子补位,返回右孩子为根节点
                return root.right
            elif root.left and not root.right: # 删除节点的右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点
                return root.left
            elif root.left and root.right:   # 既有左孩子,也有由孩子的情况
                cur = root.right
                while cur.left is not None:   # 找到右子树最左下角的一个
                    cur = cur.left
                cur.left = root.left
                return root.right
            else:          # 左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点
                return None

        if root.val>key: # left
            root.left = self.deleteNode(root.left,key)
        if root.val<key:
            root.right = self.deleteNode(root.right,key)
        return root

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

在这里插入图片描述

class Solution:
    def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
       

        if not root:
            subTree = TreeNode(val = val)
            return subTree
        
        if root.val>val:
            root.left = self.insertIntoBST(root.left,val)   # 关键点:注意返回值要接住
        if root.val<val:
            root.right = self.insertIntoBST(root.right,val)  # 关键点:注意返回值要接住
        return root
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值