前言!
此时此刻我的乖老婆在和我生气,我也好难受,我怕老婆嫌弃我不要我,很怕有会分手的那天,你如果在偷偷看我博博的话,俺想是说我欠着你很多!一辈子都还不了你,我会一辈子对你好,把心放在肚子里吧宝贝。
这里写目录标题
类型1:输出树的遍历
例题1:输出前序遍历
给定一个 N 叉树,返回其节点值的前序遍历。
例如,给定一个 3叉树 :
返回其前序遍历: [1,3,5,6,2,4 ]。
方法1:递归(最简单的做法)
class Solution(object):
def preorder(self, root):
if root==None:
return None
result=[]
def pres(root):
if root.val!=None:
result.append(root.val)#先自身
for node in root.children:#再从左到右的各孩子
pres(node)
pres(root)
return result
方法2:迭代(困难)
首先贴上代码块
class Solution(object):
def preorder(self, root):
"""
:type root: Node
:rtype: List[int]
"""
if root is None:
return []
stack = [root]
out = []
while stack:
temp = stack.pop()
out.append(temp.val)
if temp.children:
for item in temp.children[::-1]:
stack.append(item)
return out
从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
例题2:输出层次遍历
从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def levelOrder(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
if root==None: return []
stack,result,layer= [root],[],[0]
while stack:
tmp=[]
for i in range(len(stack)):
s=stack.pop(0)
tmp.append(s.val)
if s.left:
stack.append(s.left)
if s.right:
stack.append(s.right)
result.append(tmp)
return result
例题3:输出中序遍历
给定一个二叉树的根节点 root ,返回它的 中序 遍历。
class Solution(object):
def inorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
result=[]
def DFS(cur):
if not cur: return
DFS(cur.left)
result.append(cur.val)
DFS(cur.right)
DFS(root)
return result
类型4:输出后序遍历
"""
# Definition for a Node.
class Node(object):
def __init__(self, val=None, children=None):
self.val = val
self.children = children
"""
class Solution(object):
def postorder(self, root):
"""
:type root: Node
:rtype: List[int]
"""
result=[]
def DFS(root):
if not root: return
for c in root.children:
DFS(c)
result.append(root.val)
DFS(root)
return result
类型2:重建二叉树
例题1:根据前序与中序遍历
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
列:
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回:
二叉树的前序遍历顺序是:根节点、左子树、右子树,每个子树的遍历顺序同样满足前序遍历顺序。
二叉树的中序遍历顺序是:左子树、根节点、右子树,每个子树的遍历顺序同样满足中序遍历顺序。
前序遍历的第一个节点是根节点,只要找到根节点在中序遍历中的位置,在根节点之前被访问的节点都位于左子树,在根节点之后被访问的节点都位于右子树,由此可知左子树和右子树分别有多少个节点。
通过中序遍历得知左子树和右子树的节点数量之后,可以根据节点数量得到前序遍历中的左子树和右子树的分界,因此可以进一步得到左子树和右子树各自的前序遍历和中序遍历,可以通过递归的方式,重建左子树和右子树,然后重建整个二叉树。
class Solution(object):
def buildTree(self, preorder, inorder):
"""
:type preorder: List[int]
:type inorder: List[int]
:rtype: TreeNode
"""
if not preorder:
return None
#创建当前节点
node = TreeNode(preorder[0])
#查找当前的根节点在中序遍历中的位置
index = inorder.index(preorder[0])
# 划分左右子树
left_pre = preorder[1:index+1]
left_in = inorder[:index]
right_pre = preorder[index+1:]
right_in = inorder[index+1:]
# 遍历创建子树
node.left = self.buildTree(left_pre, left_in)
node.right = self.buildTree(right_pre, right_in)
# 返回当前节点
return node
例题2:有序数组构造高度平衡二叉树
将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。
直观地看,我们可以选择中间数字作为二叉搜索树的根节点,这样分给左右子树的数字个数相同或只相差 1,可以使得树保持平衡。
确定平衡二叉搜索树的根节点之后,其余的数字分别位于平衡二叉搜索树的左子树和右子树中,左子树和右子树分别也是平衡二叉搜索树,因此可以通过递归的方式创建平衡二叉搜索树。
class Solution:
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)
例题3:根据完整的前序遍历
将完整的前序遍历构造为2叉树。
完整的前序遍历结果为:【1,2,Null,Null,3,4,5】
class Solution:
def deserialize(self, data):
"""Decodes your encoded data to tree.
:type data: str
:rtype: TreeNode
"""
if not data: return
if data[0]==None:
data.pop(0)
return
root=TreeNode(data.pop(0))
if data:
root.left=self.deserialize(data)
if data:
root.right=self.deserialize(data)
return root
类型3: 深度
例题1:N 叉树的最大深度
给定一个 N 叉树,找到其最大深度。最大深度是指从根节点到最远叶子节点的最长路径上的节点总数。
例如,给定一个 3叉树 :
DFS深度优先搜索——类似于树的先根遍历,是树的先根遍历的推广
简述算法过程
1、任选一顶点作始点 v ,访问该顶点
2、沿深度方向,依次遍历 v 的未访问邻接点——直到本次遍历结束
3、一次遍历完时,若有未访问顶点:任选一个未访问顶点作起始点,GOTO第2步
算法伪代码:
DFS(dep,、、、) //dep代表目前DFS的深度
{
if(找到解 || 走不下去)
{
//在此处进行相应的操作
return ;
}
枚举下一种情况,DFS(dep+1,、、、)
}
代码为:
class Solution(object):
def maxDepth(self, root):
if not root:
return 0
depth=1
self.maxDepth=0
def DFS(depth,root):
children=root.children
if len(children)==0:
if depth>self.maxDepth:
self.maxDepth=depth
else:
for i in range(len(children)):
DFS(depth+1,children[i])
DFS(depth,root)
return self.maxDepth
例题2:2叉树的最大深度
终止条件: 当前节点为空
返回值:
节点为空时,所以返回 0
节点不为空时, 返回左右子树高度的最大值 + 1
class Solution:
def maxDepth(self, root: TreeNode) -> int:
if not root:return 0
return max(self.maxDepth(root.left),self.maxDepth(root.right))+1
例题3:2叉树的最小深度
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明:叶子节点是指没有子节点的节点。
class Solution:
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
类型4:两树判断
例题1: B是否为A子结构
输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)
B是A的子结构, 即 A中有出现和B相同的结构和节点值。
输入:A = [3,4,5,1,2], B = [4,1]
输出:true
输入:A = [1,2,3], B = [3,1]
输出:false
若树 B 是树 A 的子结构,则子结构的根节点可能为树 A 的任意一个节点。因此,判断树 B 是否是树A 的子结构,需完成以下两步工作:
1.先序遍历树 A 中的每个节点( isSubStructure(A, B))
2.判断树 A 中 以之为根节点的子树 是否包含树 B ( recur(A, B))
recur(A,B):
当B为None时,表示A已经包含B,返回True
当A为None时,表示A遍历完还没有完全B,返回False
当A.val!=B.val时,表示A不包含B,返回False
class Solution:
def isSubStructure(self, A: TreeNode, B: TreeNode) -> bool:
def recur(A, B):
if not B: return True
if not A or A.val != B.val: return False
return recur(A.left, B.left) and recur(A.right, B.right)
return bool(A and B) and (recur(A, B) or self.isSubStructure(A.left, B) or self.isSubStructure(A.right, B))
鸭子写法:
class Solution(object):
def isSubStructure(self, A, B):
def check(A,B):
if A == None: return False
if B.left == None and B.right == None:
if A.val == B.val:
return True
else:
return False
elif B.right == None :
return check(A.left,B.left)
elif B.left == None :
return check(A.right,B.right)
else:
return check(A.left,B.left) and check(A.right,B.right)
if A == None or B == None: return False
if A.val == B.val:
flag=check(A,B)
if flag: return True
else:
return self.isSubStructure(A.left, B) or self.isSubStructure(A.right, B)
else:
return self.isSubStructure(A.left, B) or self.isSubStructure(A.right, B)
例题2:两树对称
请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。
例如,二叉树 [1,2,2,3,4,4,3] 是对称的。
class Solution(object):
def isSymmetric(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
def helper(p,q):
if (p!=None and q==None) or (p==None and q!=None): return False
if p==None and q==None: return True
if p.val!=q.val:
return False
return helper(p.left,q.right) and helper(p.right,q.left)
if root==None or (root.left==None and root.right==None ): return True
return helper(root.left,root.right)
类型5:单树操作
例题1: 树的镜像
请完成一个函数,输入一个二叉树,该函数输出它的镜像。
鸭子写法:
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def mirrorTree(self, root):
if root==None: return root
if root.left or root.right:
mid=root.left
root.left=root.right
root.right=mid
self.mirrorTree(root.left)
self.mirrorTree(root.right)
return root
class Solution:
def mirrorTree(self, root: TreeNode) -> TreeNode:
if not root: return
tmp = root.left
root.left = self.mirrorTree(root.right)
root.right = self.mirrorTree(tmp)
return root
类型6:判断树的遍历序列
例题1:是否为后序遍历序列
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。
输入: [1,3,2,6,5]
输出: true
后序遍历顺序:左子节点→右子节点→根
题解:后序遍历序列之中,最后一位是根节点。因为是二叉搜索树,根节点左边的树的值一定小于他,根节点右边的树的值一定大于他,通过迭代判断:
终止条件:len(postorder)==1
判断【1,3,2,6,5】,然后判断【1,3】以及【2,6】
class Solution(object):
def verifyPostorder(self, postorder):
"""
:type postorder: List[int]
:rtype: bool
"""
if len(postorder)<=1: return True
root=postorder[-1]
pre_order,post_order=[],[]
for i in range(len(postorder)):
if postorder[i]>root:
pre_order=postorder[0:i]
post_order=postorder[i:len(postorder)-1]
break
if i==len(postorder)-1:
pre_order=postorder[0:len(postorder)-1]
if pre_order and max(pre_order)>=root:
return False
elif post_order and min(post_order)<=root:
return False
return self.verifyPostorder(pre_order) and self.verifyPostorder(post_order)