树
通用结构
from ast import List
from xmlrpc.client import Boolean
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
1. 前序遍历
def preorder(root,res=[]):
if not root:
return
res.append(root.val)
preorder(root.left, res)
preorder(root.right, res)
return res
2. 迭代前序
def preorder(root):
res= []
if not root:
return []
stack=[root]
while stack:
node=stack.pop()
res.append(node.val)
if node.right: stack.append(node.right)
if node.left: stack.append(node.left)
return res
3. 中序遍历
def inorder(root,res=[]):
if not root:
return
inorder(root.left,res)
res.append(root.val)
inorder(root.right,res)
return res
4. 后序遍历
def preorder(root,res=[]):
if not root:
return
preorder(root.left, res)
preorder(root.right, res)
res.append(root.val)
return res
5. 层次遍历
def levelOrder(self, root: TreeNode) -> List[List[int]]:
## 先处理特殊情况
if not root:
return []
## 返回结果
res = []
from collections import deque
## 定义队列
queue = deque()
## 将根节点入队
queue.append(root)
## 队列不为空,表达式二叉树还有节点,循环遍历
while queue:
## 先标记每层的节点数
size = len(queue)
## 定义变量,记录每层节点值
level = []
## 这里开始遍历当前层的节点
for _ in range(size):
## 出队
node = queue.popleft()
## 先将当前节点的值存储
level.append(node.val)
## 节点的左右节点非空时,入队
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
## 添加每层的节点值列表
res.append(level)
return res
6. 二叉树直径
def diameterOfBinaryTree(self, root: TreeNode) -> int:
self.ans = 1
def depth(node):
## 访问到空节点了,返回0
if not node:
return 0
## 左儿子为根的子树的深度
L = depth(node.left)
## 右儿子为根的子树的深度
R = depth(node.right)
## 计算d_node即L+R+1 并更新ans
self.ans = max(self.ans, L + R + 1)
## 返回该节点为根的子树的深度
return max(L, R) + 1
depth(root)
return self.ans - 1
7. 最大深度
def maxDepth(self, root):
if root is None:
return 0
left_height = self.maxDepth(root.left)
right_height = self.maxDepth(root.right)
return max(left_height, right_height) + 1
8. 最小深度
def minDepth(self, root: TreeNode) -> int:
if not root:
return 0
if not root.left and not root.right:
return 1
min_depth = 10**9
if root.left:
min_depth = min(self.minDepth(root.left), min_depth)
if root.right:
min_depth = min(self.minDepth(root.right), min_depth)
return min_depth + 1
9. 翻转二叉树
def invertTrees(self, root: TreeNode) -> TreeNode:
if not root:
return root
left = self.invertTrees(root.left)
right = self.invertTrees(root.right)
root.left,root.right = right,left
return root
10. 合并二叉树
def mergeTrees(self, t1: TreeNode, t2: TreeNode) -> TreeNode:
if not t1:
return t2
if not t2:
return t1
merge = TreeNode(t1.val+t2.val)
merge.left = self.mergeTrees(t1.left,t2.left)
merge.right = self.mergeTrees(t1.right,t2.right)
return merge
11. 二叉树的锯齿形层序遍历
def zigzagLevelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
res = []
if not root:
return res
from collections import deque
stack = deque()
stack.append(root)
level_num = 0
while stack:
level_num+=1
size = len(stack)
level = []
for _ in range(size):
node = stack.pop()
res.append(node.val)
if node.left:
stack.append(node.left)
if node.right:
stack.append(node.right)
if level_num %2 == 1:
level = level[::-1]
res.append(level)
return res
12. 最近公共祖先
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
13. 最近公共祖先 dps
def lowestCommonAncestordps(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:
parent = dict()
visit = dict()
def dps(root: TreeNode):
if not root:
return
if root.left:
parent[root.left] = root
dps(root.left)
if root.right:
parent[root.right] = root
dps(root.right)
dps(root)
while p:
visit[p] = True
p = parent[p]
while q:
if visit[q]:
return q
q = parent[q]
return None
14. 序列化
def serialize(self,root: TreeNode)->str:
sb = ""
def dfs(root):
if not root:
sb+="null"
sb+=f'{root.val},'
dfs(root.left)
dfs(root.right)
dfs(root)
return sb
15. 反序列化
def deserialize(self, data: str)-> TreeNode:
sp = data.split(",")
def build()->TreeNode:
if sp[0]=='null':
sp = sp[1:]
return None
val = int(sp[0])
sp=sp[1:]
node=TreeNode(val,build(),build())
return build()
16. 是否对称
def isSymmetric(self, root: TreeNode) -> Boolean:
def check(p,q)->Boolean:
if p==None and q ==None:
return True
if p==None or q == None:
return False
return p.val==q.val and check(p.left,q.right) and check(p.right,q.left)
return check(root,root)
17. 树高
def height(self, root: TreeNode)-> int:
if not root:
return 0
return max(self.height(root.left),self.height(root.right))+1
18. 平衡二叉树
def isBalanced(self, root: TreeNode)-> Boolean:
if not root:
return True
return abs(self.height(root.left),self.height(root.right))<=1 and self.isBalanced(root.left) and self.isBalanced(self.right)
19. 二叉搜索树 第k大节点
def kthLargest(self, root: TreeNode, k: int)->int:
def dfs(root):
if not root: return
dfs(root.right)
if k == 0: return
k -= 1
if k == 0:
res = root.val
dfs(root.left)
res = 0
dfs(root)
return res
20. 第k小的元素
def kthSmallest(self, root: TreeNode, k: int) -> int:
stack = []
while root or stack:
while root:
stack.append(root)
root = root.left
root = stack.pop()
k -= 1
if k == 0:
return root.val
root = root.right
21. 距离target节点距离为k的所有节点
def distanceK(self, root:TreeNode,target: TreeNode, k:int) -> List[int]:
parents = dict()
def dfs(root):
if not root:
return
if root.left:
parents[root.left] = root
dfs(root.left)
if root.right:
parents[root.right] = root
dfs(root.right)
dfs(root)
res = []
def findk(root:TreeNode, frm: TreeNode, deep:int):
if not root:
return
if deep == k:
res.append(root.val)
if root.left!= frm:
findk(root.left,root,deep+1)
if root.right!=frm:
findk(root.right,root,deep+1)
if parents[root]!=frm:
findk(parents[root],root,deep+1)
findk(root,None,0)
return res
22. 从前序与中序遍历序列构造二叉树
def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
def myBuildTree(preorder_left: int, preorder_right: int, inorder_left: int, inorder_right: int):
if preorder_left > preorder_right:
return None
## 前序遍历中的第一个节点就是根节点
preorder_root = preorder_left
## 在中序遍历中定位根节点
inorder_root = index[preorder[preorder_root]]
## 先把根节点建立出来
root = TreeNode(preorder[preorder_root])
## 得到左子树中的节点数目
size_left_subtree = inorder_root - inorder_left
## 递归地构造左子树,并连接到根节点
## 先序遍历中「从 左边界+1 开始的 size_left_subtree」个元素就对应了中序遍历中「从 左边界 开始到 根节点定位-1」的元素
root.left = myBuildTree(preorder_left + 1, preorder_left + size_left_subtree, inorder_left, inorder_root - 1)
## 递归地构造右子树,并连接到根节点
## 先序遍历中「从 左边界+1+左子树节点数目 开始到 右边界」的元素就对应了中序遍历中「从 根节点定位+1 到 右边界」的元素
root.right = myBuildTree(preorder_left + size_left_subtree + 1, preorder_right, inorder_root + 1, inorder_right)
return root
n = len(preorder)
## 构造哈希映射,帮助我们快速定位根节点
index = {element: i for i, element in enumerate(inorder)}
return myBuildTree(0, n - 1, 0, n - 1)
23. 从中序与后序遍历序列构造二叉树
def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode:
def helper(in_left, in_right):
## 如果这里没有节点构造二叉树了,就结束
if in_left > in_right:
return None
## 选择 post_idx 位置的元素作为当前子树根节点
val = postorder.pop()
root = TreeNode(val)
## 根据 root 所在位置分成左右两棵子树
index = idx_map[val]
## 构造右子树
root.right = helper(index + 1, in_right)
## 构造左子树
root.left = helper(in_left, index - 1)
return root
## 建立(元素,下标)键值对的哈希表
idx_map = {val:idx for idx, val in enumerate(inorder)}
return helper(0, len(inorder) - 1)
24. 将有序数组转换为二叉搜索树
def sortedArrayToBST(self, nums: List[int]) -> TreeNode:
def helper(left, right):
if left > right:
return None
## 总是选择中间位置左边的数字作为根节点
mid = (left + right) // 2
root = TreeNode(nums[mid])
root.left = helper(left, mid - 1)
root.right = helper(mid + 1, right)
return root
return helper(0, len(nums) - 1)
25. 所有路径
def binaryTreePaths(self, root):
"""
:type root: TreeNode
:rtype: List[str]
"""
def construct_paths(root, path):
if root:
path += str(root.val)
if not root.left and not root.right: ## 当前节点是叶子节点
paths.append(path) ## 把路径加入到答案中
else:
path += '->' ## 当前节点不是叶子节点,继续递归遍历
construct_paths(root.left, path)
construct_paths(root.right, path)
paths = []
construct_paths(root, '')
return paths