Day21 第六章 二叉树Part8

任务

669. 修剪二叉搜索树

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

思路

最直接的想法是,对于不符合区间范围内的节点,直接返回空,然后通过归在上层接住下面的合法节点。可是这种思路是错误的,因为加入某节点的值<low,按照之前的思路是将这个节点及其子节点全部删除,但实际上,它的右子树上的值可能是满足条件的,删除了不该删除的节点(遇到不合法直接返回空的行为)。因此,如果遇到了不合法的节点,应该在其子树继续递归的寻找合法的节点作为新的节点代替不合法的节点返回给上层,而不是直接返回空。

class Solution:
    def trimBST(self, root: Optional[TreeNode], low: int, high: int) -> Optional[TreeNode]:
        if not root: return None
        if root.val < low: #删除root,从右子树上找到合适的节点作为新root
            right = self.trimBST(root.right,low,high)
            return right
        if root.val > high: #删除root,从左子树上找到合适的节点作为新root
            left = self.trimBST(root.left,low,high)
            return left
        
        #如果当前节点在区间内,则将符合条件的左右子树接入
        root.left = self.trimBST(root.left,low,high)
        root.right = self.trimBST(root.right,low,high)
        return root

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

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

思路

在做过了106.从中序与后序遍历序列构造二叉树 和105.从前序与中序遍历序列构造二叉树,这题就比较简单,思路是一样的。

class Solution:
    def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
        if not nums: return None
        mid = len(nums)//2
        root = TreeNode(nums[mid])
        
        leftNums = nums[:mid]
        rightNums = nums[mid+1:]
        root.left = self.sortedArrayToBST(leftNums)
        root.right = self.sortedArrayToBST(rightNums)
        return root

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

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

思路

只要看懂题意,结合BST的性质,这题不难,就是按照右根左的遍历顺序依次累加前一个节点的数值。第二次访问到节点时进行累加即可,别忘了修改pre指针,这里直接用数值更简便。

class Solution:
    def __init__(self):
        self.pre = 0
    def convertBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        self.sumNode(root)
        return root
    
    def sumNode(self,node):
        if not node: return
        
        self.sumNode(node.right)
        node.val += self.pre      # 第二次访问自己时修改节点的值
        self.pre = node.val       # 并更新pre
        self.sumNode(node.left)

心得体会

至此,二叉树章节也已经步入尾声。
解决二叉树的题目关于递归的(dfs)主要思路如下:

  1. 树形DP问题,这类问题相对最简单,收集左子树信息(下层递归),收集右子树信息(下层递归),根据左右处理自己节点相关信息(局部),返回给上层。
  2. 路径相关问题,这类题目是在遍历过程中收集节点的信息,到达叶子节点后收集完一条路径,需要回溯处理(隐形局部或显性全局)
  3. 符合条件的节点问题, 这类题目是遍历到符合条件的节点后,向上返回,如果是删除插入等修改树结构的问题,有可能需要上层的指针域接住。
  4. 构造二叉树问题,这类问题是通过数组的类型(先中后序,有序数组等)来创建节点,然后将数组划分区间,递归地向左右继续创建
  5. 二叉搜索树相关问题,1.双指针法,利用中序遍历,记录pre,比较pre和node等记录信息等。 2.BST的增删查:符合条件的节点问题

总体思路为 递->向下 归->向上 该做什么

解决一些特定节点问题还可以用层序遍历,就是在层序遍历的过程中记录信息等。注意搭配层序遍历的本身写法(两层循环)

posted @ 2024-08-06 11:58  haohaoscnblogs  阅读(13)  评论(0)    收藏  举报