20.验证二叉搜索树
给定一个二叉树,判断其是否是一个有效的二叉搜索树。
假设一个二叉搜索树具有如下特征:
- 节点的左子树只包含小于当前节点的数。
- 节点的右子树只包含大于当前节点的数。
- 所有左子树和右子树自身必须也是二叉搜索树。
#递归法1 class Solution: def isValidBST(self,root:TreeNode): tmp = [] def traverse(root:TreeNode): if not root: return traverse(root.left) tmp.append(root.val) traverse(root.right) def is_sorted(nums): for i in range(1,len(nums)): if nums[i] <= nums[i - 1]: return False return True traverse(root) return is_sorted(tmp) # 递归法2 class Solution: def isValidBST(self, root: TreeNode) -> bool: # 规律: BST的中序遍历节点数值是从小到大. self.cur = -float('inf') def isValidBST(root): if not root: return True is_left_v = isValidBST(root.left) if self.cur < root.val: self.cur = root.val else: return False is_right_v = isValidBST(root.right) return is_left_v and is_right_v return isValidBST(root) #迭代法 class Solution: def isValidBST(self, root: TreeNode) -> bool: stack = [] cur = root pre = None while cur or stack: if cur: stack.append(cur) cur = cur.left else: cur = stack.pop() if pre and cur.val <= pre.val: return False pre = cur cur = cur.right return True
21.二叉搜索树的最小绝对差
-
给你一棵所有节点为非负值的二叉搜索树,请你计算树中任意两节点的差的绝对值的最小值。
#递归 class Solution: def getMinimumDifference(self, root: TreeNode) -> int: res = [] r = float('inf') def buildList(root:TreeNode): if not root: return buildList(root.left) res.append(root.val) buildList(root.right) buildList(root) for i in range(len(res) - 1): r = min(abs(res[i] - res[i + 1]),r) return r #迭代中序 class Solution: def getMinimumDifference(self, root: TreeNode) -> int: stack = [] cur = root pre = None res = float('inf') while stack or cur: if cur: stack.append(cur) cur = cur.left else: cur = stack.pop() if pre: res = min(res,cur.val - pre.val) pre = cur cur = cur.right return res
22.二叉搜索树中的众数
#递归法 class Solution: def __init__(self): self.pre = TreeNode() self.count = 0 self.max_count = 0 self.res = [] def findMode(self,root:TreeNode): if not root:return None self.searchBST(root) return self.res def searchBST(self,cur:TreeNode): if not cur: return None self.searchBST(cur.left) if not self.pre: self.count = 1 elif self.pre.val == cur.val: self.count += 1 else: self.count = 1 self.pre = cur if self.count == self.max_count: self.res.append(cur.val) if self.count > self.max_count: self.max_count = self.count self.res = [cur.val] self.searchBST(cur.right) #迭代法 class Solution: def findMode(self, root: TreeNode): stack = [] cur = root pre = None maxcount = count = 0 res = [] while cur or stack: if cur: stack.append(cur) cur = cur.left else: cur = stack.pop() if pre is None: count = 1 elif pre.val == cur.val: count += 1 else: count = 1 if count == maxcount: res.append(cur.val) if count > maxcount: maxcount = count res.clear() res.append(cur.val) pre = cur cur = cur.right return res
23.二叉树的最近公共祖先
#递归法
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if not root or root == p or root == q:return root
left = self.lowestCommonAncestor(root.left,p,q)
right = self.lowestCommonAncestor(root.right,p,q)
if not left:return right
if not right:return left
return root
24.二叉搜索树的最近公共祖先
#递归法
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if root.val > p.val and root.val > q.val:
return self.lowestCommonAncestor(root.left, p, q)
if root.val < p.val and root.val < q.val:
return self.lowestCommonAncestor(root.right, p, q)
return root
#迭代法
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
while True:
if root.val > p.val and root.val > q.val:
root = root.left
elif root.val < p.val and root.val < q.val:
root = root.right
else:
return root
25.二叉搜索树中的插入操作
#递归法
class Solution:
def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:
if not root:
return TreeNode(val)
if val < root.val:
# 将val插入至当前root的左子树中合适的位置
# 并更新当前root的左子树为包含目标val的新左子树
root.left = self.insertIntoBST(root.left, val)
if root.val < val:
# 将val插入至当前root的右子树中合适的位置
# 并更新当前root的右子树为包含目标val的新右子树
root.right = self.insertIntoBST(root.right, val)
return root
#迭代法
class Solution:
def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:
if not root:
return TreeNode(val)
cur = root
while cur:
if val < cur.val:
if not cur.left:
cur.left = TreeNode(val)
break
else:
cur = cur.left
else:
if not cur.right:
cur.right = TreeNode(val)
break
else:
cur = cur.right
return root
26.删除二叉搜索树中的节点
#递归法
class Solution:
def deleteNode(self, root: TreeNode, key: int):
# 第一种情况:没找到删除的节点,遍历到空节点直接返回了
if not root:return root
if root.val == key:
# 第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点
if not root.left and not root.right:
del root
return None
# 第三种情况:其左孩子为空,右孩子不为空,删除节点,右孩子补位 ,返回右孩子为根节点
if not root.left and root.right:
tmp = root
root = root.right
del tmp
return root
# 第四种情况:其右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点
if root.left and not root.right:
tmp = root
root = root.left
del tmp
return root
# 第五种情况:左右孩子节点都不为空,则将删除节点的左子树放到删除节点的右子树的最左面节点的左孩子的位置
else:
v = root.right
while v.left:
v = v.left
v.left = root.left
tmp = root
root = root.right
del tmp
return root
if root.val > key:root.left = self.deleteNode(root.left,key)
if root.val < key: root.right = self.deleteNode(root.right, key)
return root
27.修剪二叉搜索树
#递归法
class Solution:
def trimBST(self, root: TreeNode, low: int, high: int) -> TreeNode:
if not root:return None
if root.val < low:
# 若当前root节点小于左界:只考虑其右子树,用于替代更新后的其本身,抛弃其左子树整体
return self.trimBST(root.right,low,high)
if high < root.val:
# 若当前root节点大于右界:只考虑其左子树,用于替代更新后的其本身,抛弃其右子树整体
return self.trimBST(root.left, low, high)
if low <= root.val <= high:
root.left = self.trimBST(root.left,low,high)
root.right = self.trimBST(root.right, low, high)
# 返回更新后的剪枝过的当前节点root
return root
28.将有序数组转换为二叉搜索树
#递归法
class Solution:
def sortedArrayToBST(self, nums) -> TreeNode:
'''
构造二叉树:重点是选取数组最中间元素为分割点,左侧是递归左区间;右侧是递归右区间
必然是平衡树
左闭右闭区间
'''
# 返回根节点
root = self.traversal(nums,0,len(nums)-1)
return root
def traversal(self,nums,left,right):
if left > right:
return None
# 确定左右界的中心,防越界
mid = left + (right - left) // 2
# 构建根节点
mid_root = TreeNode(nums[mid])
# 构建以左右界的中心为分割点的左右子树
mid_root.left = self.traversal(nums,left,mid - 1)
mid_root.right = self.traversal(nums, mid + 1, right)
# 返回由被传入的左右界定义的某子树的根节点
return mid_root
29.把二叉搜索树转换为累加树
class Solution:
def convertBST(self, root: TreeNode) -> TreeNode:
def dfs(root):
if root:
dfs(root.right)
self.total += root.val
root.val = self.total
dfs(root.left)
self.total = 0
dfs(root)
return root