代码随想录day23:二叉树08(修剪二叉树,有序数组转化BST,二叉树转化为累加树,二叉树总结)

1. 修剪二叉树(leetcode 669)

这题关键在于不在范围内的树他的子树可能也在范围内,所以需要重构二叉树。

这题我们可以尝试用递归法的方式,前序遍历深度优先搜索树

递归三部曲:

1. 参数以及返回值:参数为当前节点,因为我们需要做修剪,因此通过返回值来移除节点

2. 确认终止条件:遇到空间点直接返回

3. 确定当前层逻辑:如果当前root小于low,往右递归,返回右子树返回条件的头节点

if root.val < low:
    right = self.trimBST(root.right, low, hight)
    return right

在这个步骤中我们就相当于已经把当前节点删除了,把保留下来的符合条件的右节点嫁接了过来。

总体的代码如下:

class Solution:
    def trimBST(self, root: Optional[TreeNode], low: int, high: int) -> Optional[TreeNode]:
        if not root:
            return None
 
        if root.val < low:    #当前层判断是否符合条件
            right = self.trimBST(root.right, low, high)
            return right
        if root.val > high:
            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  #这边在最后返回头节点。
        

这题的难点在于我们是怎么修剪掉我们不需要的节点,以及嫁接我们所需要的节点的。

2. 有序数组转化为BST(leetcode 108)

这题首先注意到他想让我们构建的是height-balanced BST,因此我们就不能用单边构建的方法。

如果不能单边构建,我们就不能使用迭代法,因此这题最好的方法是通过递归法,以中点为当前层节点,分别像左右递归,作为当前层的左右子集。

三部曲:

1. 参数:因为我们需要找中点,所以我们需要界定好当前层的左右范围,因此参数为数组,左范围,和右范围。

2. 终止条件:左边肯定要比右边小的,换言之当右边比左边小则终止

3. 当前层逻辑:找到中点,让中点为当前层节点,同时左右子树分别更新区间进行递归

class Solution:
    def sort(self, nums, left, right):
        if left <= right:
            mid = (left + right) // 2
            root = TreeNode(nums[mid])
            root.left = self.sort(nums, left, mid - 1)
            root.right = self.sort(nums, mid + 1, right)
            return root

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

或者我们也可以用更新nums的方式,这样我们就可以不用left and right作为参数了。

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

注意这种情况是左闭右开,所以root.left这边要取到0到mid的区间,而不是0到mid-1。

3. BST转化成累加树(leetcode 538)

这题注意到累加我们是从右下角的位置开始累加的,他的处理顺序是右中左。我们可以直接用反中序遍历的方法,同时设置指针pre cur来指向前一个节点以及当前节点,在遍历的过程中直接修改我们的树。

递归法在这里的写法是比较简单的,和我们之前的dfs递归差不多写法

class Solution:
    def traversal(self, cur):
        if not cur:
            return None

        self.traversal(cur.right)
        cur.val = cur.val + self.pre
        self.pre = cur.val
        self.traversal(cur.left)

        return cur

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

我们也尝试一下用迭代法,stack来写。

class Solution:
    def convertBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if not root: return root
        stack = []
        cur = root
        pre = 0
        while cur or stack:
            if cur:
                stack.append(cur)
                cur = cur.right
            else:
                cur = stack.pop()
                cur.val += pre
                pre = cur.val
                cur = cur.left
        return root

这种写法也是和我们之前一直在写的遍历BST的方法一样,唯一不同的只是讲左中右改成了右中左,同时多了一个pre时刻记录叠加值。迭代法很多情况下是比递归法要高效的,我们也要多写。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值