LeetCode刷题小记 七、【二叉树(二)】

1.二叉树

写在前面

本系列笔记主要作为笔者刷题的题解,所用的语言为Python3,若于您有助,不胜荣幸。

1.16从中序遍历和后序遍历构造二叉树

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

给定两个整数数组 inorderpostorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树

思路:处理的步骤是我们首先确定中间节点,即根节点,然后利用中间节点去不断切割中序遍历和后序遍历,迭代执行这一过程最后构造出完整的二叉树。

  1. 后序数组为0,空节点
  2. 后序数组最后一个元素为节点元素
  3. 寻找中序数组位置作为切割点
  4. 切中序数组
  5. 切后序数组
  6. 递归处理左区间和右区间
class Solution:
    def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
        if len(postorder) == 0 or len(inorder) == 0:        # 如果传入的非法则返回空
            return None
        rootvalue: int = postorder[-1]
        root: TreeNode = TreeNode(rootvalue)
        if len(postorder) == 1:                             # 剪枝(可省略)
            return root
        # 切割中序
        leftinorder: List[int] = inorder[:inorder.index(rootvalue)]
        rightinorder: List[int] = inorder[inorder.index(rootvalue)+1:]
        # 切割后序,中序数组大小一定和后序数组大小是相同的,所以可以用中序的大小长度来切割
        leftpostorder: List[int] = postorder[:len(leftinorder)]
        rightpostorder: List[int] = postorder[len(leftinorder): -1]
        root.left = self.buildTree(leftinorder, leftpostorder)
        root.right = self.buildTree(rightinorder, rightpostorder)
        return root

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

给定两个整数数组 preorderinorder ,其中 preorder 是二叉树的先序遍历inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。

class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
        if not preorder:
            return None
        rootval: int = preorder[0]
        root: TreeNode = TreeNode(rootval)
        if len(preorder) == 1:
            return root
        idx: int= inorder.index(rootval)
        leftinorder: List[int] = inorder[:idx]
        rightinorder: List[int] = inorder[idx+1:]
        leftpreorder: List[int] = preorder[1:1+len(leftinorder)]
        rightpreorder: List[int] = preorder[1+len(leftinorder):]

        root.left = self.buildTree(leftpreorder, leftinorder)
        root.right = self.buildTree(rightpreorder, rightinorder)
        return root

1.17最大二叉树

654. 最大二叉树

给定一个不重复的整数数组 nums最大二叉树 可以用下面的算法从 nums 递归地构建:

  1. 创建一个根节点,其值为 nums 中的最大值。
  2. 递归地在最大值 左边子数组前缀上 构建左子树。
  3. 递归地在最大值 右边子数组后缀上 构建右子树。

返回 nums 构建的 最大二叉树

思路:凡是进行构造二叉树的题目,我们都应该使用前序遍历的方式即中左右,这样我们就能先构造当前的节点,然后再构造另外两个左右子树。这道题和利用中序遍历和后序遍历数组来构造二叉树的题目比较类似,也是需要对数字进行分隔,在对数组进行分隔的时候,我们需要关注下标始终满足左闭右开的一个规则[)

解法一:给出遇到空数组的终止条件

class Solution:
    def constructMaximumBinaryTree(self, nums: List[int]) -> Optional[TreeNode]:
        if not nums:                        # 遇到空则构造None
            return None
        if len(nums) == 1:                  # 终止条件
            return TreeNode(nums[0])
        cur_val: int = max(nums)            
        cur_idx: int = nums.index(cur_val)
        root: TreeNode = TreeNode(cur_val)  # 中
        # 切割区间
        left: List[int] = nums[:cur_idx]        
        right: List[int] = nums[cur_idx+1:]
        
        root.left = self.constructMaximumBinaryTree(left)   # 左
        root.right = self.constructMaximumBinaryTree(right) # 右
        return root

解法二:不给出遇到空数组的终止条件,但要确保数组至少包含一个元素

class Solution:
    def constructMaximumBinaryTree(self, nums: List[int]) -> Optional[TreeNode]:
        if len(nums) == 1:                  # 终止条件
            return TreeNode(nums[0])
        cur_val: int = max(nums)            
        cur_idx: int = nums.index(cur_val)
        root: TreeNode = TreeNode(cur_val)  # 中
        # 切割区间
        if cur_idx > 0:         # 保证区间内至少包含一个元素
            left: List[int] = nums[:cur_idx]        
            root.left = self.constructMaximumBinaryTree(left)   # 左
        if cur_idx < len(nums) - 1:
            right: List[int] = nums[cur_idx+1:]
            root.right = self.constructMaximumBinaryTree(right) # 右
        return root

一般情况来说,如果让空节点进入递归,就不加if的条件判断,如果不让空节点进入递归,就加上if的条件判断来进行限制,终止条件也需要相应地调整。

解法三:使用下标,不切割nums

class Solution:
    def traversal(self, nums: List[int], left: int, right: int) -> Optional[TreeNode]:
        if left >= right:
            return None
        max_val_idx: int = left
        for i in range(left+1, right):
            if nums[i] > nums[max_val_idx]:
                max_val_idx = i
        root: TreeNode = TreeNode(nums[max_val_idx])
        root.left = self.traversal(nums, left, max_val_idx)
        root.right = self.traversal(nums, max_val_idx + 1, right)
        return root

    def constructMaximumBinaryTree(self, nums: List[int]) -> Optional[TreeNode]:
        return self.traversal(nums, 0, len(nums))

1.18合并二叉树

617. 合并二叉树

给你两棵二叉树: root1root2

想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。

返回合并后的二叉树。

思路:这道题需要我们同时操作两个二叉树的根节点,即root1root2,我们只需要对这两棵同步进行遍历即可,什么是同步遍历呢?就是采用相同的遍历顺序,当其中一棵树遇到空节点的时候直接采用另一棵树的节点值作为新的节点即可,如果两棵树都不是空节点,则直接返回其相加和的值即可。

解法一:递归

class Solution:
    def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
        if root1 == None:									# 终止条件
            return root2
        if root2 == None:
            return root1
        root1.val += root2.val                                  # 中,合并值
        root1.left = self.mergeTrees(root1.left, root2.left)    # 左,同步遍历
        root1.right = self.mergeTrees(root1.right, root2.right) # 右,同步遍历
        return root1

解法二:迭代,类似层序遍历

from collections import deque
class Solution:
    def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
        if not root1:
            return root2
        if not root2:
            return root1
        que: deque = deque()
        que.append((root1, root2))
        while que:
            node1, node2 = que.popleft()
            node1.val += node2.val

            if node1.left and node2.left:
                que.append((node1.left, node2.left))
            elif not node1.left:
                node1.left = node2.left

            if node1.right and node2.right:
                que.append((node1.right, node2.right))
            elif not node1.right:
                node1.right = node2.right
            
        return root1           

1.19二叉搜索树中的搜索

700. 二叉搜索树中的搜索

给定二叉搜索树(BST)的根节点 root 和一个整数值 val

你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 null

思路:二叉搜索树,需要满足的一个条件是,当前根节点的值要大于左子树的值,并且小于右子树的值,符合这种条件的树,我们可以称之为二叉搜索树。遇到二叉搜索树,我们一般采用中序遍历

解法一:递归法

class Solution:
    def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        if not root:                            # 避免传入空指针
            return None
        if root.val == val:                     # 终止条件
            return root
        elif root.val > val:                    # 左
            return self.searchBST(root.left, val)
        elif root.val < val:                    # 右
            return self.searchBST(root.right, val)

解法二:迭代法

class Solution:
    def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        if not root:                            # 避免传入空指针
            return None
        stack: List[Optional[TreeNode]] = []
        stack.append(root)
        while stack:
            cur: Optional[TreeNode] = stack.pop()
            if not cur:     
                return None
            if cur.val == val:                  # 中
                return cur
            elif cur.val > val:
                stack.append(cur.left)          # 左
            elif cur.val < val:
                stack.append(cur.right)         # 右
class Solution:
    def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        while root:
            if root.val > val: root = root.left
            elif root.val < val: root = root.right
            else: return root
        return None

1.20验证二叉搜索树

98. 验证二叉搜索树

给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。

有效 二叉搜索树定义如下:

  • 节点的左子树只包含 小于 当前节点的数。
  • 节点的右子树只包含 大于 当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。

思路:传入空指针可以被视为一种二叉搜索树,也是完全二叉树,也是完全二叉搜索树,我们可以先使用一个数组来保存二叉搜索树的中序遍历结果左中右,如果数组是有序的,那么就说明该二叉搜索树是有序的,此外我们还可以使用递归的方法来进行处理。

解法一:递归

class Solution:
    def __init__(self):
        self.max_val: float = float('-inf')
    def isValidBST(self, root: Optional[TreeNode]) -> bool:
        if not root:
            return True
        left: bool = self.isValidBST(root.left)
        # 中序遍历,验证遍历的元素是不是从小到大
        if root.val > self.max_val:
            self.max_val = root.val
        else:
            return False
        right: bool = self.isValidBST(root.right)
        return left and right
class Solution:
    def __init__(self):
        self.pre_node: Optional[TreeNode] = None
    def isValidBST(self, root: Optional[TreeNode]) -> bool:
        if not root:
            return True
        left: bool = self.isValidBST(root.left)
        # 中序遍历,验证遍历的元素是不是从小到大
        if self.pre_node and self.pre_node.val >= root.val:
            return False
        # 记录前一个节点
        self.pre_node = root
        right: bool = self.isValidBST(root.right)
        return left and right

解法二:迭代

统一迭代法的中序遍历

class Solution:
    def isValidBST(self, root: Optional[TreeNode]) -> bool:
        if not root:
            return True
        sorted_val: List[int] = []
        stack: List[Optional[TreeNode]] = []
        stack.append(root)
        while stack:
            cur: TreeNode = stack.pop()
            if cur != None:
                if cur.right != None:
                    stack.append(cur.right)     # 右
                stack.append(cur)               # 中
                stack.append(None)
                if cur.left != None:
                    stack.append(cur.left)      # 左
            else:
                cur = stack.pop()
                sorted_val.append(cur.val)
        for i in range(1, len(sorted_val)):
            if sorted_val[i] <= sorted_val[i-1]:
                return False
        return True

递归迭代法中序遍历

class Solution:
    def __init__(self):
        self.sorted_val: List[int] = []
    def traversal(self, root: Optional[TreeNode]) -> List[int]:
        if not root:
            return
        self.traversal(root.left)
        self.sorted_val.append(root.val)
        self.traversal(root.right)

    def isValidBST(self, root: Optional[TreeNode]) -> bool:
        self.traversal(root)
        if not self.sorted_val:
            return True
        for i in range(1, len(self.sorted_val)):
            if self.sorted_val[i] <= self.sorted_val[i-1]:
                return False
        return True

1.21二叉搜索树的最小绝对差

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

给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值

差值是一个正数,其数值等于两值之差的绝对值。

解法一:递归

class Solution:
    def __init__(self):
        self.result: int = float('inf')
        self.pre: Optional[TreeNode] = None
    
    def traversal(self, cur: Optional[TreeNode]) -> None:
        if not cur:
            return
        self.traversal(cur.left)                                    # 左
        if self.pre != None:
            self.result = min(self.result, abs(cur.val - self.pre.val)) # 中
        self.pre = cur
        self.traversal(cur.right)                                   # 右

    def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
        if not root:                        # 避免传入空指针
            return -1
        self.traversal(root)
        return self.result

解法二:递归,然后查找

class Solution:
    def __init__(self):
        self.result: int = float('inf')
        self.vals: List[int] = []
    def traversal(self, cur: Optional[TreeNode]) -> None:
        if not cur:
            return
        self.traversal(cur.left)
        self.vals.append(cur.val) # 将二叉搜索树转换为有序数组,中序遍历
        self.traversal(cur.right)

    def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
        self.traversal(root)
        for i in range(1, len(self.vals)):
                self.result = min(self.result, abs(self.vals[i] - self.vals[i-1]))
        return self.result

783. 二叉搜索树节点最小距离

给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值

差值是一个正数,其数值等于两值之差的绝对值。

这两道题是一样的题目,可以同时解决。

1.22二叉搜索树中的众数

501. 二叉搜索树中的众数

给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。

如果树中有不止一个众数,可以按 任意顺序 返回。

假定 BST 满足如下定义:

  • 结点左子树中所含节点的值 小于等于 当前节点的值
  • 结点右子树中所含节点的值 大于等于 当前节点的值
  • 左子树和右子树都是二叉搜索树

解法一:先递归得到一个map,然后从这个map中查找最大的key

class Solution:
    def __init__(self):
        self.num_map: dict = {}

    def traversal(self, cur: Optional[TreeNode]) -> None:
        if not cur:
            return 
        self.traversal(cur.left)                                    # 左
        self.num_map[cur.val] = self.num_map.get(cur.val, 0) + 1    # 中
        self.traversal(cur.right)                                   # 右
        
    def findMode(self, root: Optional[TreeNode]) -> List[int]:
        self.traversal(root)
        max_val: int = max(self.num_map.values())
        res: List[int] = [key for key, value in self.num_map.items() if value == max_val]
        return res

解法二:双指针法递归

class Solution:
    def __init__(self):
        self.result: List[int] = []
        self.pre: Optional[TreeNode] = None
        self.maxCount: int = 0
        self.count: int = 0

    def traversal(self, cur: Optional[TreeNode]) -> None:
        if not cur:
            return 
        self.traversal(cur.left)            # 左
        if self.pre == None:                # 中
            self.count = 1
        elif self.pre.val == cur.val:
            self.count += 1
        else:
            self.count = 1
        self.pre = cur
        if self.count == self.maxCount:
            self.result.append(cur.val)
        elif self.count > self.maxCount:
            self.maxCount = self.count
            self.result.clear()             # 清空result结果集
            self.result.append(cur.val)
        self.traversal(cur.right)           # 右
        return 

    def findMode(self, root: Optional[TreeNode]) -> List[int]:
        self.traversal(root)
        return self.result

1.23二叉树的最近公共祖先

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

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        if not root:
            return None
        if root == p or root == q:
            return root
        left: TreeNode = self.lowestCommonAncestor(root.left, p, q)           # 左
        right: TreeNode = self.lowestCommonAncestor(root.right, p, q)         # 右
        if left != None and right != None:                              # 中
            return root
        elif left != None and right == None:
            return left
        elif left == None and right != None:
            return right
        else:
            return None

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

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

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

思路:当我们从上往下遍历的时候,如果,遇到一个节点的值在pq之间的话,那么就一定能说明这是这棵二叉搜索树的最近公共祖先吗?这一点确实能保证当前的节点就是二叉搜索树的最近公共祖先,因为如果当前的节点的值满足在pq之间,就表明pq一定分别在当前节点的左右子树中,所以这个节点就一定是最近公共祖先。

解法一:递归法

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        if not root:
            return None
        if root.val > p.val and root.val > q.val:                       # 左
            left: TreeNode = self.lowestCommonAncestor(root.left, p, q)
            if left != None:
                return left
        if root.val < p.val and root.val < q.val:                       # 右
            right: TreeNode = self.lowestCommonAncestor(root.right, p, q)
            if right != None:
                return right
        return root

解法二:迭代法

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        if not root:
            return None
        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:
                return root

1.25二叉搜索树中的插入操作

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

给定二叉搜索树(BST)的根节点 root 和要插入树中的值 value ,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。

注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果

解法一:迭代法+双指针

class Solution:
    def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        if not root:                        # 防止传入空指针
            return TreeNode(val)
        cur: Optional[TreeNode] = root
        pre: Optional[TreeNode] = None
        while cur:
            pre = cur
            if cur.val > val:
                cur = cur.left
            elif cur.val < val:
                cur = cur.right
        if pre.val > val:
            pre.left = TreeNode(val)
        elif pre.val < val:
            pre.right = TreeNode(val)
        return root

解法二:递归法

class Solution:
    def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        if root == None:
            return TreeNode(val)
        if root.val > val:                                      # 左
            left: TreeNode = self.insertIntoBST(root.left, val)
            root.left = left
        elif root.val < val:                                    # 右
            right: TreeNode = self.insertIntoBST(root.right, val)
            root.right = right
        return root

1.26删除二叉搜索树中的节点

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

给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。

一般来说,删除节点可分为两个步骤:

  1. 首先找到需要删除的节点;
  2. 如果找到了,删除它。

思路:我们需要考虑查找节点的几种情况,然后分情况讨论

  • 情况一:没找到要删除的节点
  • 情况二:待删除的节点是叶子节点
  • 情况三:待删除的节点左不为空右为空
  • 情况四:待删除的节点左为空右不为空
  • 情况五:待删除的节点左不为空右不为空
class Solution:
    def deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]:
        if not root:
            return None
        if root.val == key:
            if root.left == None and root.right == None:            # 情况二:待删除的节点是叶子节点
                return None
            elif root.left != None and root.right == None:          # 情况三:待删除的节点左不为空右为空
                return root.left
            elif root.left == None and root.right != None:          # 情况四:待删除的节点左为空右不为空
                return root.right
            else:                                                   # 情况五:待删除的节点左不为空右不为空
                cur: Optional[TreeNode] = root.right
                while cur.left:
                    cur = cur.left
                cur.left = root.left
                return root.right
        elif root.val > key:
            root.left = self.deleteNode(root.left, key)
        elif root.val < key:
            root.right = self.deleteNode(root.right, key)
        
        return root             # 情况一:没找到要删除的节点

1.27修剪二叉搜索树

给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树,使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即,如果没有被移除,原有的父代子代关系都应当保留)。 可以证明,存在 唯一的答案

所以结果应当返回修剪好的二叉搜索树的新的根节点。注意,根节点可能会根据给定的边界发生改变。

class Solution:
    def trimBST(self, root: Optional[TreeNode], low: int, high: int) -> Optional[TreeNode]:
        if not root:
            return None
        if root.val < low:                  # 向右修剪
            return root.right				# 这样写是不对的,因为当前root的right中不全是符合区间条件的node
        elif root.val > high:               # 向左修剪
            return root.left
        else:                               # 接收返回值
            root.left = self.trimBST(root.left, low, high)
            root.right = self.trimBST(root.right, low, high)
        return root

正确的Solution

class Solution:
    def trimBST(self, root: Optional[TreeNode], low: int, high: int) -> Optional[TreeNode]:
        if not root:
            return None
        if root.val < low:                  # 向右修剪
            right: TreeNode = self.trimBST(root.right, low, high)
            return right
        elif root.val > high:               # 向左修剪
            left: TreeNode = self.trimBST(root.left, low, high)
            return left
        else:                               # 接收返回值
            root.left = self.trimBST(root.left, low, high)
            root.right = self.trimBST(root.right, low, high)
        return root

1.28将有序数组转换成二叉搜索树

108. 将有序数组转换为二叉搜索树

给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 平衡 二叉搜索树。

递归法:左闭右闭

class Solution:
    def traversal(self, nums: List[int], left: int, right: int) -> Optional[TreeNode]:
        """
        当前定义的区间是左闭右闭的
        """
        if left > right:
            return None
        mid: int = (left + right) // 2          # 这里一定是整除
        root: Optional[TreeNode] = TreeNode(nums[mid])
        root.left = self.traversal(nums, left, mid-1)
        root.right = self.traversal(nums, mid+1, right)
        return root

    def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
        return self.traversal(nums, 0, len(nums)-1)

递归法:左闭右开

class Solution:
    def traversal(self, nums: List[int], left: int, right: int) -> Optional[TreeNode]:
        """
        当前定义的区间是左闭右开的
        """
        if left >= right:
            return None
        mid: int = (left + right) // 2          # 这里一定是整除
        root: Optional[TreeNode] = TreeNode(nums[mid])
        root.left = self.traversal(nums, left, mid)
        root.right = self.traversal(nums, mid+1, right)
        return root

    def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
        return self.traversal(nums, 0, len(nums))

1.29把二叉搜索树转换成累加树

538. 把二叉搜索树转换为累加树

给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。

提醒一下,二叉搜索树满足下列约束条件:

  • 节点的左子树仅包含键 小于 节点键的节点。
  • 节点的右子树仅包含键 大于 节点键的节点。
  • 左右子树也必须是二叉搜索树。

1038. 从二叉搜索树到更大和树

给定一个二叉搜索树 root (BST),请将它的每个节点的值替换成树中大于或者等于该节点值的所有节点值之和。

提醒一下, 二叉搜索树 满足下列约束条件:

  • 节点的左子树仅包含键 小于 节点键的节点。
  • 节点的右子树仅包含键 大于 节点键的节点。
  • 左右子树也必须是二叉搜索树。

这两道题目又是一样的题目。

思路:使用中序遍历的逆序,为什么呢?因为对二叉搜索树使用中序遍历,我们就能获得一个有序的数组,为了从高到低处理节点,我们使用中序遍历的逆序,这样直接处理的就是节点值最大的节点了。

解法一:递归法

class Solution:
    def __init__(self):
        self.pre: Optional[TreeNode] = None

    def traversal(self, cur: Optional[TreeNode]) -> None:
        """
        中序遍历的逆序
        """
        if not cur:
            return None
        self.traversal(cur.right)           # 右
        if self.pre:
            cur.val += self.pre.val         # 中
        self.pre = cur
        self.traversal(cur.left)            # 左

    def convertBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if not root:
            return None
        self.traversal(root)
        return root

解法二:迭代法

class Solution:
    def __init__(self):
        self.pre: Optional[TreeNode] = None
    
    def traversal(self, cur: Optional[TreeNode]) -> None:
        if not cur:
            return None
        stack: List[TreeNode] = []
        while cur or stack:
            if cur:
                stack.append(cur)   
                cur = cur.right                 # 右
            else:
                cur = stack.pop()               # 中
                if self.pre:
                    cur.val += self.pre.val
                self.pre = cur
                cur = cur.left                  # 左

    def convertBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        self.traversal(root)
        return root

Reference

[1] Hello 算法
[2] 代码随想录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值