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