day21 二叉树part08

669. 修剪二叉搜索树

题目链接:. - 力扣(LeetCode)

文章讲解:代码随想录

视频讲解:你修剪的方式不对,我来给你纠正一下!| LeetCode:669. 修剪二叉搜索树_哔哩哔哩_bilibili

Python

递归法(版本一)

class Solution:
    def trimBST(self, root: TreeNode, low: int, high: int) -> TreeNode:
        if root is None:
            # 如果当前节点为空,直接返回空
            return None
        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.left 接入符合条件的左孩子
        root.right = self.trimBST(root.right, low, high)  # root.right 接入符合条件的右孩子
        return root  # 返回当前节点

迭代法

class Solution:
    def trimBST(self, root: TreeNode, L: int, R: int) -> TreeNode:
        if not root:
            # 如果当前节点为空,直接返回空
            return None
        
        # 处理头结点,使得root移动到[L, R] 范围内,注意是左闭右闭区间
        while root and (root.val < L or root.val > R):
            if root.val < L:
                # 如果当前节点值小于L,说明该节点和它的左子树都不在范围内,移动到右子树
                root = root.right
            else:
                # 如果当前节点值大于R,说明该节点和它的右子树都不在范围内,移动到左子树
                root = root.left
        
        # 此时root已经在[L, R] 范围内,开始处理左子树中的节点,使其都在[L, R] 范围内
        cur = root
        while cur:
            while cur.left and cur.left.val < L:
                # 如果左孩子的值小于L,将左孩子修剪掉,并接上左孩子的右子树
                cur.left = cur.left.right
            # 移动到左孩子继续处理
            cur = cur.left
        
        # 此时root已经在[L, R] 范围内,开始处理右子树中的节点,使其都在[L, R] 范围内
        cur = root
        while cur:
            while cur.right and cur.right.val > R:
                # 如果右孩子的值大于R,将右孩子修剪掉,并接上右孩子的左子树
                cur.right = cur.right.left
            # 移动到右孩子继续处理
            cur = cur.right
        
        # 返回修剪后的树的根节点
        return root

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

题目链接:https://leetcode.cn/problems/convert-sorted-array-to-binary-search-tree/

文章讲解:代码随想录

视频讲解:构造平衡二叉搜索树!| LeetCode:108.将有序数组转换为二叉搜索树_哔哩哔哩_bilibili

Python

递归法

class Solution:
    def traversal(self, nums: List[int], left: int, right: int) -> TreeNode:
        if left > right:
            # 如果左边界大于右边界,说明当前子数组为空,返回空节点
            return None
        
        # 取中间位置元素作为根节点,以保证平衡性
        mid = left + (right - left) // 2
        root = 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]) -> TreeNode:
        # 从有序数组构建平衡二叉搜索树
        root = self.traversal(nums, 0, len(nums) - 1)
        return root  # 返回构建好的平衡二叉搜索树的根节点

递归 精简(自身调用)

class Solution:
    def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
        # 如果输入数组为空,返回None表示空节点
        if not nums:
            return None
        
        # 找到数组的中间元素作为当前子树的根节点
        mid = len(nums) // 2
        
        # 创建当前子树的根节点
        root = TreeNode(nums[mid])
        
        # 递归构建左子树,左子树由数组左半部分元素构成
        root.left = self.sortedArrayToBST(nums[:mid])
        
        # 递归构建右子树,右子树由数组右半部分元素构成
        root.right = self.sortedArrayToBST(nums[mid + 1:])
        
        # 返回当前子树的根节点
        return root

迭代法

from collections import deque
from typing import List, Optional

# 定义二叉树节点类
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution:
    def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
        if len(nums) == 0:
            # 如果输入数组为空,返回None表示空节点
            return None
        
        root = TreeNode(0)  # 创建初始根节点,值先设为0
        nodeQue = deque()   # 用于存放遍历的节点
        leftQue = deque()   # 用于存放左区间的下标
        rightQue = deque()  # 用于存放右区间的下标
        
        # 初始化队列
        nodeQue.append(root)               # 将根节点入队列
        leftQue.append(0)                  # 左区间下标初始位置为0
        rightQue.append(len(nums) - 1)     # 右区间下标初始位置为数组长度减1

        # 当队列不为空时进行循环
        while nodeQue:
            # 取出当前处理的节点和对应的左右区间下标
            curNode = nodeQue.popleft()
            left = leftQue.popleft()
            right = rightQue.popleft()
            mid = left + (right - left) // 2  # 计算中间位置的下标

            # 将中间位置的元素赋值给当前节点
            curNode.val = nums[mid]

            # 处理左区间
            if left <= mid - 1:
                curNode.left = TreeNode(0)  # 创建左子节点
                nodeQue.append(curNode.left)  # 将左子节点入队列
                leftQue.append(left)  # 将左区间的左边界入队列
                rightQue.append(mid - 1)  # 将左区间的右边界入队列

            # 处理右区间
            if right >= mid + 1:
                curNode.right = TreeNode(0)  # 创建右子节点
                nodeQue.append(curNode.right)  # 将右子节点入队列
                leftQue.append(mid + 1)  # 将右区间的左边界入队列
                rightQue.append(right)  # 将右区间的右边界入队列

        # 返回构建好的二叉搜索树的根节点
        return root

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

题目链接:. - 力扣(LeetCode)

文章链接:代码随想录

视频链接:https://www.bilibili.com/video/BV1d44y1f7wP?share_source=copy_web

Python

递归法(版本一)

# 定义二叉树节点类
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

class Solution:
    def convertBST(self, root: TreeNode) -> TreeNode:
        self.pre = 0  # 记录前一个节点的累加数值
        self.traversal(root)  # 从根节点开始遍历
        return root  # 返回修改后的根节点
    
    def traversal(self, cur: TreeNode):
        if cur is None:
            # 如果当前节点为空,直接返回
            return
        
        # 递归遍历右子树
        self.traversal(cur.right)
        
        # 修改当前节点的值,累加前一个节点的值
        cur.val += self.pre
        # 更新前一个节点的累加值为当前节点的值
        self.pre = cur.val
        
        # 递归遍历左子树
        self.traversal(cur.left)

递归法(版本二)

# 定义二叉树节点类
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

class Solution:
    def __init__(self):
        self.count = 0  # 初始化累加器,记录累加的值

    def convertBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if root is None:
            # 如果当前节点为空,返回None
            return None

        '''
        倒序累加替换:
        使用反向中序遍历(右->中->左)来遍历树,并更新每个节点的值
        '''

        # 递归遍历右子树
        self.convertBST(root.right)

        # 中间节点处理
        self.count += root.val  # 更新累加器,累加当前节点的值
        root.val = self.count   # 更新当前节点的值为累加后的值

        # 递归遍历左子树
        self.convertBST(root.left)

        # 返回修改后的根节点
        return root

迭代法(版本一)

class Solution:
    def __init__(self):
        self.pre = 0  # 记录前一个节点的数值,初始为0
    
    def traversal(self, root):
        stack = []  # 初始化栈,用于迭代遍历
        cur = root  # 当前节点设为根节点
        
        # 当当前节点不为空或栈不为空时继续循环
        while cur or stack:
            if cur:
                stack.append(cur)  # 当前节点入栈
                cur = cur.right  # 遍历右子树
            else:
                cur = stack.pop()  # 弹出栈顶节点进行处理
                cur.val += self.pre  # 更新当前节点的值
                self.pre = cur.val  # 更新前一个节点的累加值
                cur = cur.left  # 遍历左子树
    
    def convertBST(self, root):
        self.pre = 0  # 重置累加值
        self.traversal(root)  # 调用遍历方法
        return root  # 返回修改后的根节点

迭代法(版本二)

class Solution:
    def convertBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if not root: 
            # 如果树根为空,直接返回空
            return root
        
        stack = []  # 初始化栈,用于迭代遍历
        cur = root  # 当前节点设为根节点
        pre = 0  # 记录前一个节点的累加值,初始为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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值