2024.4.(3,8,21号)力扣刷题记录-二叉树学习记录3

一、学习视频

验证二叉搜索树_哔哩哔哩_bilibili

二、视频跟练代码

题目:

98. 验证二叉搜索树

解题:

(1)递归。按照灵神的说法这个叫做前序遍历。

# 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 isValidBST(self, root: Optional[TreeNode]) -> bool:
        # 递归
        # 递归左右范围
        def f(node, l, r) -> bool:
            if node is None:
                return True
            x = node.val
            if x <= l or x >= r:
                return False
            leftBool = f(node.left, l, x)    #缩短右边范围,左边范围不变,而不是无限
            rightBool = f(node.right, x, r)
            return leftBool and rightBool
        return f(root, -inf, inf)

(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 isValidBST(self, root: Optional[TreeNode]) -> bool:
        # 中序遍历,不调用自身
        # 节点值从小到大
        pre = -inf
        def f(node) -> bool:
            nonlocal pre
            if node is None:
                return True
            if not f(node.left):
                return False
            if node.val <= pre:     #注意是小于等于,中序遍历
                return False
            pre = node.val  #遍历下一个节点,更新pre
            return f(node.right)
        return f(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:
    pre = -inf
    def isValidBST(self, root: Optional[TreeNode]) -> bool:
        # 中序遍历,调用自身
        if root is None:
            return True
        if not self.isValidBST(root.left):
            return False
        # if root.val <= Solution.pre:
        if root.val <= self.pre:     #注意是小于等于,中序遍历
            return False
        # Solution.pre = root.val
        self.pre = root.val  #遍历下一个节点,更新pre
        return self.isValidBST(root.right)

注意:这里是self.pre而不是Solution.pre。前者是实例变量,随着实例不同值不同;后者是类变量,随着实例不同值相同,是同一个变量。

(3)后序遍历。来自视频。

# 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 isValidBST(self, root: Optional[TreeNode]) -> bool:
        # 后序遍历
        # 返回节点数字范围,归
        # 拿左节点的最大值,右节点的最小值
        def f(node):
            if node is None:
                return inf, -inf
            l_min, l_max = f(node.left)
            r_min, r_max = f(node.right)
            x = node.val
            if l_max < x < r_min:
                return min(l_min, x), max(r_max, x)
            else:
                return -inf, inf
        return True if (f(root)) != (-inf, inf) else False

三、课后作业练习

1.700. 二叉搜索树中的搜索

(1)递归

前序遍历,类似二分。

# 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 searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        # 递归,前序遍历,类似二分
        # 注意是二叉搜索树
        if root is None:
            return None
        x = root.val
        if x == val:
            return root
        elif x > val:
            left = self.searchBST(root.left, val)
            return left if left else None
        else:
            right = self.searchBST(root.right, val)
            return right if right else None

参考官方题解(. - 力扣(LeetCode)),空可以不用返回。对上一代码进行优化:

# 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 searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        # 递归,前序遍历,类似二分
        # 注意是二叉搜索树
        if root is None:
            return None
        x = root.val
        if x == val:
            return root
        return self.searchBST(root.left if x > val else root.right, val)

或写成一行,来自题解(. - 力扣(LeetCode))。

(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 searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        # 迭代
        while root:
            if val == root.val:
                return root
            root = root.left if root.val > val else root.right
        return None

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

(1)中序遍历

# 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:
    pre = -inf
    minGap = inf
    def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
        # 中序遍历
        # 二叉搜索树中序遍历严格递增
        if root is None:    #为空差值为正无穷
            return inf
        leftGap = self.getMinimumDifference(root.left)
        self.minGap = min(self.minGap, leftGap, root.val - self.pre)    #更新最小gap
        self.pre = root.val     #更新上一节点
        self.getMinimumDifference(root.right)   #遍历右
        return self.minGap

 (2)中序遍历+迭代器。来自题解(. - 力扣(LeetCode))。

# 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 getMinimumDifference(self, root: Optional[TreeNode]) -> int:
        # 中序遍历+迭代器
        def f(node):    #迭代器
            if not node:
                return
            yield from f(node.left)
            yield node.val
            yield from f(node.right)
        return min(b - a for a, b in pairwise(f(root)))

其中yield用来产生生成器,学习链接:http://t.csdnimg.cn/j9tDx

下段来自chatgpt:

yield from 是 Python 3.3 引入的语法,用于简化生成器函数(generator function)中的 yield 语句的嵌套。它的作用是将一个可迭代对象(比如另一个生成器)中产生的值直接传递给外层的生成器。

使用迭代器进行中序遍历。

pairwise函数相关解释,下段来自chatgpt:

 pairwise 函数通常用于在一个序列中生成相邻的元素对。这个函数在给定一个序列时,会返回一个迭代器,每次产生相邻的两个元素组成的元组。这样可以方便地在迭代中处理相邻元素。

 使用pairwise函数对中序遍历后的迭代器相邻两项进行相减。

2024.4.8续:

3.2476. 二叉搜索树最近节点查询

(1)中序遍历数组+排序。将中序遍历结果用数组存起来。

# 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 closestNodes(self, root: Optional[TreeNode], queries: List[int]) -> List[List[int]]:
        # 中序遍历数组+排序
        # 二叉搜索树的中序遍历相当于有序数组,得到数组
        tree = []
        def Tree(node):
            if node is None:
                return 
            Tree(node.left)
            tree.append(node.val)
            Tree(node.right)
        Tree(root)
        treeN = len(tree)

        n = len(queries)
        ans = [0] * n
        idx = list(range(n))
        idx.sort(key=lambda x : queries[x])

        treeIndex = 0
        for i in idx:
            target = queries[i]
            mn, mx = -1, -1
            while treeIndex < treeN:
                mx = tree[treeIndex]
                if mx >= target:
                    if mx == target:
                        mn = target
                    elif treeIndex > 0:
                        mn = tree[treeIndex - 1]
                    break
                treeIndex += 1
            if treeIndex == treeN:
                mn, mx = tree[-1], -1
            ans[i] = [mn, mx]
        return ans

(2) 中序遍历数组+二分查找。来自灵神题解(. - 力扣(LeetCode))。有一瞬间脑子里闪过了使用二分,但仅仅只是一瞬间,还是不够熟练啊。

# 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 closestNodes(self, root: Optional[TreeNode], queries: List[int]) -> List[List[int]]:
        # 中序遍历数组+二分查找
        tree = []
        def Tree(node):
            if node is None:
                return 
            Tree(node.left)
            tree.append(node.val)
            Tree(node.right)
        Tree(root)
        treeN = len(tree)

        # 二分过程
        ans = []
        for q in queries:
            idx = bisect.bisect_left(tree, q)
            mx = tree[idx] if idx < treeN else -1
            if idx == treeN or tree[idx] != q:
                idx -= 1
            mn = tree[idx] if idx >= 0 else -1
            ans.append([mn, mx])
        return ans

4. 501. 二叉搜索树中的众数

(1)中序遍历+哈希表(需额外空间)

# 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 findMode(self, root: Optional[TreeNode]) -> List[int]:
        # 中序遍历+哈希表(需额外空间)
        hash = {}
        def tree(node):
            if node is None:
                return 
            tree(node.left)
            x = node.val
            hash[x] = hash.get(x, 0) + 1
            tree(node.right)
        tree(root)
        
        maxcnt = 0
        ans = []
        for k, v in hash.items():
            if v > maxcnt:  #更新
                ans = [k]
                maxcnt = v
            elif v == maxcnt:
                ans.append(k)
        return ans

(2)直接中序遍历。参考官方题解(. - 力扣(LeetCode))。

# 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 findMode(self, root: Optional[TreeNode]) -> List[int]:
        # 直接中序遍历
        curValue, maxCnt, curCnt = -10**5-1, 0, 0
        ans = []
        def f(node):
            nonlocal ans
            nonlocal curValue, maxCnt, curCnt
            if node is None:
                return 
            f(node.left)
            x = node.val
            # 更新curCnt
            if x == curValue:       
                curCnt += 1
            else:
                curValue = x # 更新curValue
                curCnt = 1
            # 更新maxCnt
            if curCnt == maxCnt:
                ans.append(curValue)
            if curCnt > maxCnt:
                ans = [curValue]
                maxCnt = curCnt
            f(node.right)
        f(root)
        return ans

下面列举几个博主在写该题时出现的问题:

  •  记录的是上一个节点的值与次数。我本来使用的方法是记录上一个节点,认为这样更新ans列表才不会出错。写出代码后,没有报错,但是结果不一样,仔细一想,这样的话没有包括最后遍历的那个节点,看完官方题解后发现,记录当前节点才是正确的。
  • 那么为什么记录当前节点是正确的呢?博主之前认为,当curCnt == maxCnt时,在当前节点就将当前节点添加到ans中不太正确。后来仔细思考后发现,在curCnt == maxCnt的下一个节点处会出现两种情况1.等于上一个,那么此时curCnt > maxCnt,会对ans进行更新,原来的数组就不需要了,添加的值也就不会影响;2.不等于上一个,那么上一个节点curCnt == maxCnt,不会再增加,而且已经被添加进去了。所以在当前节点就将当前节点添加到ans中是没有问题的。
  • 在解题时,我还想到使用之前的做法,将这三个参数作为函数参数传入或者作为返回值,这样想在这里是有问题的。首先作为函数参数传入的值是“递”的“东西”,返回值是“归”的“东西”,我们需要统一进行“递”传递东西,再“归”返回我们想要的东西。但是此题使用的是中序遍历,中序遍历先“递”左子树、“归”左子树,再“递”右子树、“归”右子树,这里是没有办法进行统一递归的,传参也比较困难。

 2024.4.21续:

(3)Morris中序遍历,参考官方题解。

不会这个算法,去学习了一下。学习笔记为:http://t.csdnimg.cn/SWasY

# 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 findMode(self, root: Optional[TreeNode]) -> List[int]:
        # Morris中序遍历
        curValue, maxCnt, curCnt = -10**5-1, 0, 0
        ans = []
        def update(x: int):
            nonlocal curValue, maxCnt, curCnt
            nonlocal ans
            # 更新curCnt
            if x == curValue:       
                curCnt += 1
            else:
                curValue = x # 更新curValue
                curCnt = 1
            # 更新maxCnt
            if curCnt == maxCnt:
                ans.append(curValue)
            if curCnt > maxCnt:
                ans = [curValue]
                maxCnt = curCnt
        # Morris中序遍历过程
        cur = root
        while cur:
            if not cur.left:
                update(cur.val)     #中序到达中间节点时更新
                cur = cur.right
            else:
                pre = cur.left
                while pre.right and pre.right != cur:
                    pre = pre.right
                if pre.right is None:
                    pre.right = cur
                    cur = cur.left
                else:
                    pre.right = None    #删除线索
                    update(cur.val)     #中序到达中间节点时更新
                    cur = cur.right
        return ans

5.230. 二叉搜索树中第K小的元素

(1)递归,中序遍历。

# 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 kthSmallest(self, root: Optional[TreeNode], k: int) -> int:
        # 递归,中序遍历
        ans = -1
        def f(node):
            nonlocal ans, k
            if node is None:
                return
            f(node.left)
            if k < 0:
                return
            elif k == 1:
                # 找到了
                k = -1
                ans = node.val
                return
            else:
                k -= 1
            f(node.right)
        f(root)
        return ans

(2)Morris中序遍历

# 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 kthSmallest(self, root: Optional[TreeNode], k: int) -> int:
        # # 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 kthSmallest(self, root: Optional[TreeNode], k: int) -> int:
        # Morris中序遍历
        cur = root
        while cur:
            if cur.left is None:
                if k == 1:
                    return cur.val
                else:
                    k -= 1
                cur = cur.right
            else:
                pre = cur.left
                while pre.right and pre.right != cur:
                    pre = pre.right
                if pre.right is None:
                    pre.right = cur
                    cur = cur.left
                else:
                    if k == 1:
                        return cur.val
                    else:
                        k -= 1
                    pre.right = None
                    cur = cur.right
        cur = root
        while cur:
            if cur.left is None:
                if k == 1:
                    return cur.val
                else:
                    k -= 1
                cur = cur.right
            else:
                pre = cur.left
                while pre.right and pre.right != cur:
                    pre = pre.right
                if pre.right is None:
                    pre.right = cur
                    cur = cur.left
                else:
                    if k == 1:
                        return cur.val
                    else:
                        k -= 1
                    pre.right = None
                    cur = cur.right

 (3)通过栈实现中序遍历,来自官方题解(. - 力扣(LeetCode))。

# 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 kthSmallest(self, root: Optional[TreeNode], k: int) -> int:
        # 通过栈实现中序遍历
        stack = []
        while root or stack:
            while root:
                # 将当前节点及其所有左节点全部压入栈
                stack.append(root)
                root = root.left
            root = stack.pop()
            k -= 1
            if k == 0:
                return root.val
            # 遍历右子树
            root = root.right

 (4)生成器中序遍历,来自题解(. - 力扣(LeetCode))。

# 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 kthSmallest(self, root: Optional[TreeNode], k: int) -> int:
        # 生成器中序遍历
        def f(node):
            if node is None:
                return
            yield from f(node.left)
            yield node.val
            yield from f(node.right)

        it = f(root)    #将生成器对象赋值给it
        for _ in range(k - 1):
            # 消耗前k-1个数
            next(it)
        return next(it)

6.1373. 二叉搜索子树的最大键值和 

后序遍历

# 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 maxSumBST(self, root: Optional[TreeNode]) -> int:
        # 后序遍历
        # 边验证二叉搜索树,边更新
        # 返回值为树的左边界,右边界,子树和
        maxSum = 0
        def f(node):
            nonlocal maxSum
            if node is None:
                return inf, -inf, 0
            lmin, lmax, ls = f(node.left)
            rmin, rmax, rs = f(node.right)
            x = node.val
            if lmax < x < rmin:
                # 是二叉搜索树
                curSum = x + ls + rs
                maxSum = max(maxSum, curSum)
                return min(lmin, x), max(rmax, x), curSum
            else:
                return -inf, inf, 0
        f(root)
        return maxSum

7. 105. 从前序与中序遍历序列构造二叉树

不会,以下均来自灵神题解(. - 力扣(LeetCode))。

(1)递归

# 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 buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
        # 递归
        # 根据前序和中序性质
        # if preorder is None:      # 错误的
        if not preorder:
            return None
        left_size = inorder.index(preorder[0])  #左子树大小
        left = self.buildTree(preorder[1:1 + left_size], inorder[:left_size])
        right = self.buildTree(preorder[1 + left_size:], inorder[left_size+1:])
        return TreeNode(preorder[0], left, right)   #构造树

其中博主在使用if preorder is None为条件时报错,因为此处preorder是列表。和if not preorder区别如下,来自chatgpt:

在 Python 中,`if not preorder` 和 `if preorder is None` 在处理条件时有一些微妙的区别。

1. **`if not preorder`:** 这个条件检查 preorder 是否为 False 或者是否为空。如果 preorder 是一个空列表、空字符串、0、None 等 Python 中被视为 False 的值,那么条件就会成立,执行其下的代码块。但如果 preorder 是一个非空的列表,即使列表里的元素全部是 0 或者空字符串等被视为 False 的值,这个条件也会被视为 True,因为列表本身不是空的。

2. **`if preorder is None`:** 这个条件则明确地检查 preorder 是否为 None。如果 preorder 是 None,条件成立,执行其下的代码块。如果 preorder 是一个空列表、空字符串、0 或者其他被视为 False 的值,这个条件也不成立,因为它不是 None。

因此,如果你想要检查 preorder 是否为空列表或者 None,那么 `if not preorder` 是更适合的选择。如果你只想检查 preorder 是否为 None,那么使用 `if preorder is None` 更明确。

(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 buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
        # 递归优化
        # 哈希表记录中序下标
        index = {x: i for i, x in enumerate(inorder)}

        def f(pre_l: int, pre_r: int, in_l: int, in_r: int):
            # 左闭右开,如同切片
            # 将切片列表改为指针
            if pre_l == pre_r:  #空节点
                return None
            left_size = index[preorder[pre_l]] - in_l   #中序根节点下标 - 中序左边界
            left = f(pre_l + 1, pre_l + 1 + left_size, in_l, in_l + left_size)
            right = f(pre_l + 1 + left_size, pre_r, in_l + left_size + 1, in_r)
            return TreeNode(preorder[pre_l], left, right)
        return f(0, len(preorder), 0, len(inorder))

 8.106. 从中序与后序遍历序列构造二叉树

做法和前一道题类似

(1)递归,切片。

# 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 buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
        # 递归,切片
        if not postorder:
            return None
        left_size = inorder.index(postorder[-1])
        left = self.buildTree(inorder[:left_size], postorder[:left_size])
        right = self.buildTree(inorder[left_size + 1:], postorder[left_size:-1])
        return TreeNode(postorder[-1], left, right)

(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 buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
        # 递归优化,哈希表+左右指针
        index = {x: i for i, x in enumerate(inorder)}
        def f(in_l: int, in_r: int, post_l: int, post_r: int):
            if post_l == post_r:
                return None
            left_size = index[postorder[post_r-1]] - in_l   #注意右边是开区间,需要减一
            left = f(in_l, in_l + left_size, post_l, post_l + left_size)
            right = f(in_l + left_size + 1, in_r, post_l + left_size, post_r - 1)
            return TreeNode(postorder[post_r-1], left, right)
        return f(0, len(inorder), 0, len(postorder))

9. 889. 根据前序和后序遍历构造二叉树

跟前面差不多,根节点为前序第一个(且为后序最后一个)。另外,题目中为什么说答案不唯一呢?是因为不含中序遍历是无法唯一确定二叉树的(前+中、后+中可以,前+后不行)。

(1)递归

# 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 constructFromPrePost(self, preorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
        # 递归
        # 后序的倒数第二个节点是根节点的右节点
        # 以此将左右子树分开即可
        if not preorder or not postorder:
            return None
        if len(postorder) == 1:
            return TreeNode(postorder[-1], None, None)
        left_size = preorder.index(postorder[-2]) - 1
        left = self.constructFromPrePost(preorder[1: left_size + 1], postorder[: left_size])
        right = self.constructFromPrePost(preorder[left_size + 1:], postorder[left_size: -1])
        return TreeNode(postorder[-1], left, right)

(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 constructFromPrePost(self, preorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
        # 递归优化
        # 哈希表
        index = {x: i for i, x in enumerate(preorder)}
        
        def f(pre_l, pre_r, post_l, post_r):
            if post_l == post_r:
                return None
            if (post_r - post_l) == 1:
                return TreeNode(postorder[post_r - 1], None, None)
            left_size = index[postorder[post_r - 2]] - pre_l - 1    #右开
            left = f(pre_l + 1, pre_l + left_size + 1, post_l, post_l + left_size)
            right = f(pre_l + left_size + 1, pre_r, post_l + left_size, post_r - 1)
            return TreeNode(postorder[post_r - 1], left, right)
        return f(0, len(preorder), 0, len(postorder))

10.1110. 删点成林

后序遍历

# 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 delNodes(self, root: Optional[TreeNode], to_delete: List[int]) -> List[TreeNode]:
        # 后序遍历
        def f(node) -> (Optional[TreeNode], List[TreeNode]):
            if not node:
                return None, []
            left_tree, left_list = f(node.left)
            right_tree, right_list = f(node.right)
            if node.val in to_delete:
                if left_tree:
                    left_list.append(left_tree)
                if right_tree:
                    right_list.append(right_tree)
                return None, left_list + right_list
            else:
                node.left = left_tree
                node.right = right_tree
                return node, left_list + right_list
        root_tree, root_list = f(root)
        if root_tree:
            root_list.append(root_tree)
        return root_list
        

参考灵神题解(. - 力扣(LeetCode)),对上述代码进行优化,优化方面如下:

  • 如何快速查找node.val是不是在to_delete:

我之前还想过使用二分查找函数,但是对于这道题来说还是感觉不太方便。使用集合实现快速查找,下段来自chatgpt:

在 Python 中,使用集合(set)来存储数据可以实现快速的查找操作。这是因为集合是基于哈希表实现的数据结构,具有 O(1) 的平均时间复杂度来执行查找操作。所以,如果你有一个列表 to_delete,并且你想要快速检查某个元素是否在其中,可以将它转换为集合,然后使用 in 运算符来进行查找。

  • 把返回列表改为维护非局部变量。
  • 将返回的左右树节点直接赋值为根节点的左右节点。

修改代码如下: 

# 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 delNodes(self, root: Optional[TreeNode], to_delete: List[int]) -> List[TreeNode]:
        # 后序遍历优化
        ans = []
        s = set(to_delete)
        def f(node) -> Optional[TreeNode]:
            if not node:
                return None
            node.left = f(node.left)
            node.right = f(node.right)
            if node.val not in s:
                return node
            if node.left:
                ans.append(node.left)
            if node.right:
                ans.append(node.right)
            return None
        if f(root):
            ans.append(root)
        return ans

感谢你看到这里!一起加油吧!

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值