二叉树试题(Python实现)
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
目录
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
1. 二叉树的层序遍历
非递归队列实现
import queue
class Solution:
def levelOrder(self , root: TreeNode) -> List[List[int]]:
res = []
if root is None: return res
# 队列实现
q = queue.Queue()
q.put(root)
while not q.empty():
now = []
n = q.qsize()
for _ in range(n):
cur = q.get()
now.append(cur.val)
if cur.left: q.put(cur.left)
if cur.right: q.put(cur.right)
res.append(now)
return res
递归使用深度depth记录
class Solution:
res = []
def traverse(self, root: TreeNode, depth: int):
if root:
# 检查当前深度
if len(self.res) < depth:
now = []
self.res.append(now)
now.append(root.val)
else:
now = self.res[depth-1]
now.append(root.val)
else: return
# 递归左右子树深度+1
self.traverse(root.left, depth + 1)
self.traverse(root.right, depth + 1)
def levelOrder(self , root: TreeNode) -> List[List[int]]:
if root is None: return self.res
self.traverse(root, 1)
return self.res
2. 二叉树的最大深度层序遍历
二叉树的最大深度_牛客题霸_牛客网 (nowcoder.com)
class Solution:
def maxDepth(self , root: TreeNode) -> int:
if root is None: return 0
return max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1
非递归队列实现
import queue
class Solution:
def maxDepth(self , root: TreeNode) -> int:
res = 0
if root is None: return res
q = queue.Queue()
q.put(root)
while not q.empty():
n = q.qsize()
for _ in range(n):
cur = q.get()
if cur.left: q.put(cur.left)
if cur.right: q.put(cur.right)
res += 1
return res
3. 按之字形顺序打印二叉树层序遍历变形
按之字形顺序打印二叉树_牛客题霸_牛客网 (nowcoder.com)
import queue
class Solution:
def Print(self , pRoot: TreeNode) -> List[List[int]]:
res = []
if pRoot is None: return res
q = queue.Queue()
q.put(pRoot)
flag = True
while not q.empty():
now = []
flag = not flag
n = q.qsize()
for _ in range(n):
cur = q.get()
now.append(cur.val)
if cur.left: q.put(cur.left)
if cur.right: q.put(cur.right)
# 偶数行反转
if flag:
now = now[::-1]
res.append(now)
return res
4. 二叉树中和为某一值的路径层序遍历变形
二叉树中和为某一值的路径(一)_牛客题霸_牛客网 (nowcoder.com)
class Solution:
def hasPathSum(self , root: TreeNode, sum: int) -> bool:
if root is None: return False
if root.left is None and root.right is None and root.val == sum: return True
return self.hasPathSum(root.left, sum-root.val) or self.hasPathSum(root.right, sum-root.val)
非递归栈实现
class Solution:
def hasPathSum(self , root: TreeNode, sum: int) -> bool:
if root is None: return False
# 模拟栈
s = []
s.append((root, root.val))
while len(s):
cur = s[-1]
s.pop()
if not cur[0].left and not cur[0].right and cur[1] == sum:
return True
if cur[0].left:
s.append((cur[0].left, cur[1] + cur[0].left.val))
if cur[0].right:
s.append((cur[0].right, cur[1] + cur[0].right.val))
return False
5. 二叉树的前序遍历
class Solution:
# 递归前序遍历
def preorder(self, ls: List[int], root: TreeNode):
if root is None: return
ls.append(root.val)
self.preorder(ls, root.left)
self.preorder(ls, root.right)
def preorderTraversal(self , root: TreeNode) -> List[int]:
ls = []
self.preorder(ls, root)
return ls
非递归栈实现
class Solution:
def preorderTraversal(self , root: TreeNode) -> List[int]:
res = []
if root is None: return res
# 模拟栈
s = []
s.append(root)
while s:
cur = s[-1]
# 拿到之后pop走
s.pop()
res.append(cur.val)
# 后进先出先放右节点再放左节点
if cur.right: s.append(cur.right)
if cur.left: s.append(cur.left)
return res
6. 二叉树的中序遍历
class Solution:
# 递归中序遍历
def inorder(self, ls: List[int], root: TreeNode):
if root is None: return
self.inorder(ls, root.left)
ls.append(root.val)
self.inorder(ls, root.right)
def inorderTraversal(self , root: TreeNode) -> List[int]:
ls = []
self.inorder(ls, root)
return ls
非递归栈实现
class Solution:
def inorderTraversal(self , root: TreeNode) -> List[int]:
res = []
if root is None: return res
# 模拟栈
s = []
while root or s:
# 将根节点存入栈走到最左子节点
while root:
s.append(root)
root = root.left
# 获得最左子节点
cur = s[-1]
s.pop()
res.append(cur.val)
# 走到右节点
root = cur.right
return res
7. 二叉树的后序遍历
class Solution:
# 递归后序遍历
def postorder(self, ls: List[int], root: TreeNode):
if root is None: return
self.postorder(ls, root.left)
self.postorder(ls, root.right)
ls.append(root.val)
def postorderTraversal(self , root: TreeNode) -> List[int]:
ls = []
self.postorder(ls, root)
return ls
非递归栈实现
class Solution:
def postorderTraversal(self , root: TreeNode) -> List[int]:
res = []
if root is None: return res
# 模拟栈
s = []
# 记录访问过的元素
pre = None
while root or s:
# 将根节点存入栈走到最左子节点
while root:
s.append(root)
root = root.left
# 获得最左子节点
cur = s[-1]
s.pop()
# 如果右子树为空或已访问过
if cur.right is None or cur.right is pre:
res.append(cur.val)
pre = cur
else:
s.append(cur)
root = cur.right
return res
8. 对称的二叉树
对称的二叉树_牛客题霸_牛客网 (nowcoder.com)
class Solution:
# 递归比较两节点是否对称
def cmp(self, root1: TreeNode, root2: TreeNode) -> bool:
if root1 is None and root2 is None: return True
if root1 is None or root2 is None or root1.val != root2.val: return False
return self.cmp(root1.left, root2.right) and self.cmp(root1.right, root2.left)
def isSymmetrical(self , pRoot: TreeNode) -> bool:
return self.cmp(pRoot, pRoot)
非递归双队列实现
import queue
class Solution:
def isSymmetrical(self , pRoot: TreeNode) -> bool:
if pRoot is None: return True
q1 = queue.Queue()
q2 = queue.Queue()
q1.put(pRoot.left)
q2.put(pRoot.right)
while not q1.empty() and not q2.empty():
left = q1.get()
right = q2.get()
# 都为空则继续
if left is None and right is None:
continue
# 只有一侧为空 或 val不相等则不对称
if left is None or right is None or left.val != right.val:
return False
q1.put(left.left)
q1.put(left.right)
q2.put(right.right)
q2.put(right.left)
return True
9. 合并二叉树
class Solution:
def mergeTrees(self , t1: TreeNode, t2: TreeNode) -> TreeNode:
if t1 is None: return t2
if t2 is None: return t1
head = TreeNode(t1.val + t2.val)
head.left = self.mergeTrees(t1.left, t2.left)
head.right = self.mergeTrees(t1.right, t2.right)
return head
非递归三队列实现
import queue
class Solution:
def mergeTrees(self , t1: TreeNode, t2: TreeNode) -> TreeNode:
if t1 is None: return t2
if t2 is None: return t1
head = TreeNode(t1.val + t2.val)
q = queue.Queue()
q1 = queue.Queue()
q2 = queue.Queue()
q.put(head)
q1.put(t1)
q2.put(t2)
while not q1.empty() and not q2.empty():
cur, cur1, cur2 = q.get(), q1.get(), q2.get()
l1, r1, l2, r2 = cur1.left, cur1.right, cur2.left, cur2.right
if l1 or l2:
if l1 and l2:
left = TreeNode(l1.val + l2.val)
cur.left = left
q.put(left)
q1.put(l1)
q2.put(l2)
else:
cur.left = l1 if l1 else l2
if r1 or r2:
if r1 and r2:
right = TreeNode(r1.val + r2.val)
cur.right = right
q.put(right)
q1.put(r1)
q2.put(r2)
else:
cur.right = r1 if r1 else r2
return head
10. 二叉树的镜像
二叉树的镜像_牛客题霸_牛客网 (nowcoder.com)
class Solution:
def Mirror(self , pRoot: TreeNode) -> TreeNode:
if pRoot is None: return None
left = self.Mirror(pRoot.left)
right = self.Mirror(pRoot.right)
pRoot.left, pRoot.right = right, left
return pRoot
非递归栈实现
class Solution:
def Mirror(self , pRoot: TreeNode) -> TreeNode:
if pRoot is None: return None
# 模拟栈
s = []
s.append(pRoot)
while s:
cur = s[-1]
s.pop()
if cur.left:
s.append(cur.left)
if cur.right:
s.append(cur.right)
# 直接交换树节点左右子树
cur.left, cur.right = cur.right, cur.left
return pRoot
11. 判断是不是二叉搜索树
判断是不是二叉搜索树_牛客题霸_牛客网 (nowcoder.com)
import sys
class Solution:
# 最值记录
pre = -sys.maxsize -1
def isValidBST(self , root: TreeNode) -> bool:
if root is None: return True
# 左子树
if not self.isValidBST(root.left):
return False
if root.val <= self.pre:
return False
# 更新最值
self.pre = root.val
if not self.isValidBST(root.right):
return False
return True
非递归栈实现中序遍历
class Solution:
def isValidBST(self , root: TreeNode) -> bool:
s = []
res = []
while root or s:
# 走到左子节点
while root:
s.append(root)
root = root.left
root = s[-1]
s.pop()
res.append(root.val)
root = root.right
# 检查中序遍历结果即可
for i in range(1, len(res)):
if res[i -1] > res[i]:
return False
return True
12. 判断是不是完全二叉树
判断是不是完全二叉树_牛客题霸_牛客网 (nowcoder.com)
队列实现层序遍历
import queue
class Solution:
def isCompleteTree(self , root: TreeNode) -> bool:
if root is None: return True
q = queue.Queue()
q.put(root)
flag = False
while not q.empty():
size = q.qsize()
for _ in range(size):
cur = q.get()
if cur is None:
flag = True
else:
if flag: return False
q.put(cur.left)
q.put(cur.right)
return True
13. 判断是不是平衡二叉树
判断是不是平衡二叉树_牛客题霸_牛客网 (nowcoder.com)
自顶向下递归
class Solution:
# 计算深度
def depth(self, root: TreeNode) -> int:
if root is None: return 0
return max(self.depth(root.left), self.depth(root.right)) + 1
def IsBalanced_Solution(self, pRoot: TreeNode) -> bool:
if pRoot is None: return True
left = self.depth(pRoot.left)
right = self.depth(pRoot.right)
# 当前节点左右子树深度是否小于1
if abs(left-right) > 1: return False
# 检查左右子树是否都平衡
return self.IsBalanced_Solution(pRoot.left) and self.IsBalanced_Solution(pRoot.right)
自底向上
class Solution:
# 计算深度
def depth(self, root: TreeNode) -> int:
if root is None: return 0
# 左子树
left = self.depth(root.left)
if left == -1: return -1
# 右子树
right = self.depth(root.right)
if right == -1: return -1
return -1 if abs(left - right) > 1 else max(left,right) + 1
def IsBalanced_Solution(self , pRoot: TreeNode) -> bool:
if pRoot is None: return True
return self.depth(pRoot) != -1
14. 二叉搜索树的最近公共祖先
二叉搜索树的最近公共祖先_牛客题霸_牛客网 (nowcoder.com)
class Solution:
def lowestCommonAncestor(self , root: TreeNode, p: int, q: int) -> int:
if root is None: return -1
if (p >= root.val and q <= root.val) or (p <= root.val and q >= root.val):
return root.val
elif p <= root.val and q <= root.val:
return self.lowestCommonAncestor(root.left, p, q)
else:
return self.lowestCommonAncestor(root.right, p, q)
非递归搜索路径比较
class Solution:
# 得到搜索路径
def getPath(self, root: TreeNode, target: int) -> List[int]:
res = []
while root.val != target:
res.append(root.val)
if target < root.val:
root = root.left
else:
root = root.right
res.append(root.val)
return res
def lowestCommonAncestor(self , root: TreeNode, p: int, q: int) -> int:
# 求根节点到两个节点的路径
path_p = self.getPath(root, p)
path_q = self.getPath(root, q)
for i in range(min(len(path_p), len(path_q))):
# 一直走到路径不相等时结束循环
if path_p[i] == path_q[i]:
res = path_p[i]
else:
break
return res
15. 两个节点的最近公共祖先
在二叉树中找到两个节点的最近公共祖先_牛客题霸_牛客网 (nowcoder.com)
class Solution:
def lowestCommonAncestor(self , root: TreeNode, o1: int, o2: int) -> int:
if root is None: return -1
if root.val == o1 or root.val == o2:
return root.val
left = self.lowestCommonAncestor(root.left, o1, o2)
right = self.lowestCommonAncestor(root.right, o1, o2)
if left == -1: return right
if right == -1: return left
# 否则是当前节点
return root.val
非递归深度优先搜索dfs
class Solution:
# 记录是否找到o的路径
flag = False
# 计算根节点到目标节点的路径
def dfs(self, root: TreeNode, path: List[int], o: int):
if self.flag or root is None: return
path.append(root.val)
if root.val == o:
self.flag = True
return
self.dfs(root.left, path, o)
self.dfs(root.right, path, o)
if self.flag:
return
# 否则该子树没有回溯
path.pop()
def lowestCommonAncestor(self , root: TreeNode, o1: int, o2: int) -> int:
path1, path2 = [], []
self.dfs(root, path1, o1)
# 重置flag
self.flag = False
self.dfs(root, path2, o2)
res = None
# 一直走到路径不相等时结束循环
for i in range(min(len(path1), len(path2))):
if path1[i] == path2[i]:
res = path1[i]
else:
break
return res
16. 二叉搜索树 转 双向链表
二叉搜索树与双向链表_牛客题霸_牛客网 (nowcoder.com)
递归实现中序遍历
class Solution:
head = None
pre = None
def Convert(self , pRootOfTree ):
if pRootOfTree is None: return None
# 递归找到最小值
self.Convert(pRootOfTree.left)
# 头节点初始化
if self.pre is None:
self.head = pRootOfTree
self.pre = pRootOfTree
# 当前节点与上一点建立连接
else:
self.pre.right = pRootOfTree
pRootOfTree.left = self.pre
self.pre = pRootOfTree
self.Convert(pRootOfTree.right)
return self.head
非递归栈实现
class Solution:
def Convert(self , pRootOfTree ):
if pRootOfTree is None: return None
# 模拟栈
s = []
head = None
pre = None
# 标记最小值最左子节点
flag = True
while pRootOfTree or s:
while pRootOfTree:
s.append(pRootOfTree)
pRootOfTree = pRootOfTree.left
pRootOfTree = s[-1]
s.pop()
# 头节点初始化
if flag:
head = pRootOfTree
pre = head
flag = False
else:
pre.right = pRootOfTree
pRootOfTree.left = pre
pre = pRootOfTree
pRootOfTree = pRootOfTree.right
return head
17. 序列化二叉树
序列化二叉树_牛客题霸_牛客网 (nowcoder.com)
class Solution:
def __init__(self) -> None:
self.index = 0
self.s = ""
# 序列化
def Serialize(self, root):
# 空节点 #
if root is None:
self.s += '#'
return self.s
# 根节点 !
self.s += (str)(root.val) + '!'
# 左子树
self.Serialize(root.left)
# 右子树
self.Serialize(root.right)
return self.s
# 反序列化
def Deserialize(self, s):
if s == "#": return None
if self.index >= len(s) or s[self.index] == "#":
self.index += 1
return None
val = 0
while s[self.index] != '!' and self.index != len(s):
val = val*10 + (int)(s[self.index])
self.index += 1
root = TreeNode(val)
if self.index == len(s):
return root
else:
self.index += 1
root.left = self.Deserialize(s)
root.right = self.Deserialize(s)
return root
18. 重建二叉树
class Solution:
def reConstructBinaryTree(self , pre: List[int], vin: List[int]) -> TreeNode:
n = len(pre)
m = len(vin)
if n == 0 or m == 0: return None
root = TreeNode(pre[0])
for i in range(n):
# 在中序遍历中找到前序遍历的根节点
if pre[0] == vin[i]:
# 左子树前序
leftpre = pre[1:i+1]
# 左子树中序
leftvin = vin[:i]
# 左子树
root.left = self.reConstructBinaryTree(leftpre, leftvin)
# 右子树前序
rightpre = pre[i+1:]
# 右子树中序
rightvin = vin[i+1:]
root.right = self.reConstructBinaryTree(rightpre, rightvin)
break
return root
非递归栈实现
class Solution:
def reConstructBinaryTree(self , pre: List[int], vin: List[int]) -> TreeNode:
n = len(pre)
m = len(vin)
if n == 0 or m == 0: return None
s = []
# 根节点
root = TreeNode(pre[0])
cur = root
j = 0
for i in range(1, n):
if cur.val != vin[j]:
cur.left = TreeNode(pre[i])
s.append(cur)
cur = cur.left
else:
j += 1
while s and s[-1].val == vin[j]:
cur = s[-1]
s.pop()
j += 1
cur.right = TreeNode(pre[i])
cur = cur.right
return root
19. 输出二叉树的右视图
输出二叉树的右视图_牛客题霸_牛客网 (nowcoder.com)
层序遍历+哈希表
from collections import defaultdict
import queue
class Solution:
index = defaultdict(int)
# 建树函数
# 四个int参数分别是前序最左节点下标前序最右节点下标
# 中序最左节点下标中序最右节点坐标
def buildTree(self, xianxu: List[int], l1: int, r1: int, zhongxu: List[int], l2: int, r2:int) -> TreeNode:
if l1 > r1 or l2 > r2:
return None
# 前序遍历中的第一个节点就是根节点
xianxu_root = l1
# 在中序遍历中定位根节点
zhongxu_root = self.index[xianxu[xianxu_root]]
root = TreeNode(xianxu[xianxu_root])
# 得到左子树中的节点数目
leftsize = zhongxu_root - l2
root.left = self.buildTree(xianxu, l1 + 1, l1 + leftsize, zhongxu, l2, zhongxu_root - 1)
root.right = self.buildTree(xianxu, l1 + leftsize + 1, r1, zhongxu, zhongxu_root + 1, r2)
return root
#层次遍历
def rightSideView(self, root: TreeNode) -> List[int]:
res = []
q = queue.Queue()
q.put(root)
while not q.empty():
#队列中的大小即是这一层的节点树
size = q.qsize()
while size:
size -= 1
temp = q.get()
if temp.left:
q.put(temp.left)
if temp.right:
q.put(temp.right)
#最右元素
if size == 0:
res.append(temp.val)
return res
def solve(self , xianxu: List[int], zhongxu: List[int]) -> List[int]:
res = []
# 空节点
if len(xianxu) == 0:
return res
for i in range(len(xianxu)):
self.index[zhongxu[i]] = i
# 建树
root = self.buildTree(xianxu, 0, len(xianxu) - 1, zhongxu, 0, len(zhongxu) - 1)
# 找每一层最右边的节点
return self.rightSideView(root)