本篇全部集中在二叉树相关问题上,是参考东哥的思路进行的练习和思考。东哥有《labuladong 的算法小抄》以及宝藏微信公众号 labuladong,github 也有项目,自来水推荐购买和关注。
def rangeSumBST(self, root: TreeNode, low: int, high: int) -> int:
# 本函数接受一个根节点(指针)作为输入,返回该根节点下,满足要求的节点和
if not root: return 0
res = 0
if low <= root.val <= high:
res += root.val
# 剪掉左侧分支
elif root.val < low:
res += self.rangeSumBST(root.right, low, high)
return res
# 剪掉右侧分支
elif root.val > high:
res += self.rangeSumBST(root.left, low, high)
return res
# 不需要剪枝的情况
res += self.rangeSumBST(root.left, low, high)
res += self.rangeSumBST(root.right, low, high)
return res
def isValidBST(self, root: TreeNode) -> bool:
def check(root, min_node, max_node):
# 本函数接受一个根节点(指针),节点值应该满足一定条件
# max node 和 min node 负责维护当前 root 应该满足的条件
# 如果 max 和 min 为空,那么没有危险
# 如果 max 或 min 不为空,那么就要满足对应条件
if not root: return True
if min_node and root.val <= min_node.val: return False
if max_node and root.val >= max_node.val: return False
return check(root.left, min_node, root) and check(root.right, root, max_node)
return check(root, None, None)
def trimBST(self, root: TreeNode, low: int, high: int) -> TreeNode:
# 本函数接受根节点(指针)作为输入,返回该指针对应树被修剪之后的树的根节点
# 空指针最乖了
if not root: return None
# 爸爸有案底,左子代直接剪掉,但是右子代还存疑
if root.val < low:
return self.trimBST(root.right, low, high)
# 爸爸有案底,右子代直接剪掉,但是左子代还存疑
elif 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
class BSTIterator:
# 模拟栈,看了以前的提交,嘿嘿,中序遍历取 index 做的哈哈哈
def __init__(self, root: TreeNode):
self.stack = []
self.push_all_left(root)
def push_all_left(self, root):
while root :
self.stack.append(root)
root = root.left
def next(self) -> int:
last_node = self.stack.pop()
self.push_all_left(last_node.right)
return last_node.val
def hasNext(self) -> bool:
return len(self.stack) != 0
附加题目:
def kthSmallest(self, root: TreeNode, k: int) -> int:
# 这个题中序遍历整个二叉树也可以,但是不够高效
# 关键是控制程序在找到目标之后及时停下来
# 之前是写的 helper 在中间停止了,现在补一版模拟栈
self.stack = []
def push_all_left(root):
while root:
self.stack.append(root)
root = root.left
return
push_all_left(root)
while k:
last_node = self.stack.pop()
k -= 1
push_all_left(last_node.right)
return last_node.val
def bstFromPreorder(self, preorder: List[int]) -> TreeNode:
# 因为条件是二叉搜索树的前序遍历,所以 root 在最前面,其左子树所有节点都比它的值小
# 根据这点可以判断左子树边界,一旦确定子树边界,递归就完事儿了
# 我这里用 for 循环做的
def build(start, end):
if start > end: return None
root = TreeNode(preorder[start])
left_size = 0
for i in range(start + 1, end + 1):
if preorder[i] < root.val:
left_size += 1
else:
break
root.left = build(start + 1, start + left_size)
root.right = build(start + left_size + 1, end)
return root
return build(0, len(preorder) - 1)