代码随想录算法训练营Day23 | 669. 修剪二叉搜索树 | 108. 将有序数组转换为二叉搜索树 | 538. 把二叉搜索树转换为累加树 | 二叉树完结

669. 修剪二叉搜索树

题目链接 | 解题思路

和删除 BST 节点的操作看上去很相似,同样是通过返回节点来重构 BST。但实际上比删除节点要简单:当因为上下限而删除节点的时候,直接返回相对应的递归后的左子树或者右子树即可。相比之下,删除特定节点需要在找到节点后手动进行删除,不能借助递归。

本题的重点在于,可以依靠返回值进行快速重构,同时意识到需要删除时应当递归其子树而不是直接返回 None。

class Solution:
    def trimBST(self, root: Optional[TreeNode], low: int, high: int) -> Optional[TreeNode]:
        if root == None:
            return None
        
        # leaf node, whether to trim or not
        if root.left == None and root.right == None:
            if root.val > high or root.val < low:
                return None
            else:
                return root
        
        # whether to trim current node
        if root.val < low:
            return self.trimBST(root.right, low, high)
        if root.val > high:
            return self.trimBST(root.left, low, high)
        
        root.left = self.trimBST(root.left, low, high)
        root.right = self.trimBST(root.right, low, high)
        return root

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

题目链接 | 解题思路

构造 BST,一不小心就平衡了。 \hspace{40ex} - 代码随想录

根据数组构建 BST,重要的是找到左右区间。一般默认是取数组的中间元素作为节点,即可构成平衡 BST。
如果数组长度为偶数,中间节点有两个,此时取任意一节点都可以,答案不唯一。

可以通过传递当前区间的 index 来进一步优化空间使用,又要保证循环不变量:一直是左闭右开或者左闭右闭。

class Solution:
    def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
        if len(nums) == 0:
            return None
        if len(nums) == 1:
            return TreeNode(val=nums[0])
        
        mid_idx = len(nums) // 2
        root = TreeNode(val=nums[mid_idx])

        root.left = self.sortedArrayToBST(nums[:mid_idx])
        root.right = self.sortedArrayToBST(nums[mid_idx+1:])

        return root

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

题目链接 | 解题思路

将其看作是递增数组从右向左累加的话就很熟悉了,在 BST 中的遍历顺序应该是右中左

同样可以通过双指针的方法,记录前一个节点的数值(已修改过),方便之后节点的累加。但直接依靠全局变量计算累加和更方便些。

class Solution:
    def __init__(self):
        self.increment = 0

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

        # right
        root.right = self.convertBST(root.right)

        # middle
        self.increment += root.val
        root.val = self.increment

        # left
        root.left = self.convertBST(root.left)

        return root

二叉树完结

二叉树总结篇

二叉树的遍历方式:

  • 深度优先
    • 前序遍历:前左右
    • 中序遍历:前中右
    • 后序遍历:左右中
  • 广度优先
    • 层序遍历(队列)

遍历顺序的选择:

  • 涉及到二叉树的构造,无论普通二叉树还是 BST 一定前序,都是先构造中节点。
  • 求普通二叉树的属性,一般是后序,一般要通过递归函数的返回值做计算。
  • 求二叉搜索树的属性,一定是中序了,要不白瞎了有序性。

注意在普通二叉树的属性中,我用的是一般为后序,例如单纯求深度就用前序。257 中也用了前序,这是为了方便让父节点指向子节点。

删除二叉搜索树中的节点 是一道值得再看的题。以重构的方式进行节点删除,免除了记录父节点的麻烦,是一个非常精妙的方法。同时,本题也有很多种终止条件的分类,值得理清思路。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值