一、层序遍历
遍历记录
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def levelOrderBottom(self, root: TreeNode) -> List[List[int]]:
if not root:return []
results=[] # 记录所有层的结果
from collections import deque
que=deque([root]) # 存储所有元素的结果
while que:
result=[]
for i in range(len(que)):
cur=que.popleft()
result.append(cur.val)
if cur.left:que.append(cur.left)
if cur.right:que.append(cur.right)
results.append(result)
return results[::-1]
"""
# Definition for a Node.
class Node:
def __init__(self, val=None, children=None):
self.val = val
self.children = children
"""
class Solution:
def levelOrder(self, root: 'Node') -> List[List[int]]:
results=[]
if not root:return
from collections import deque
que=deque([root])
while que:
result=[]
for i in range(len(que)):
cur=que.popleft()
result.append(cur.val)
if cur.children:que.extend(cur.children) # 注意这里的children是多个结点,所以要用extend才能够一个个放进que中
results.append(result)
return results
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def rightSideView(self, root: TreeNode) -> List[int]:
res=[] # 记录最终结果
if not root:return res
from collections import deque
que=deque([root]) # 存储所有元素
# deque相比list的好处是,list的pop(0)是O(n)复杂度,deque的popleft()是O(1)复杂度
while que:
cur=que[-1] # 目前指针指向的节点
res.append(cur.val)
for i in range(len(que)):
cur=que.popleft()
if cur.left:que.append(cur.left)
if cur.right:que.append(cur.right)
return res
求层均值、max、计数
class Solution:
def averageOfLevels(self, root: Optional[TreeNode]) -> List[float]:
results=[]
if not root:return
from collections import deque
que=deque([root])
while que:
sum=0
size=len(que)
for i in range(size):
cur=que.popleft()
sum+=cur.val
if cur.left:que.append(cur.left)
if cur.right:que.append(cur.right)
results.append(sum/size)
return results
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def largestValues(self, root: TreeNode) -> List[int]:
if not root:return []
import math
from collections import deque
que=deque([root])
res=[]
while que:
res_max=-math.inf # 初始化每一层的最大值
for i in range(len(que)):
cur=que.popleft()
res_max=max(res_max,cur.val)
if cur.left:que.append(cur.left)
if cur.right:que.append(cur.right)
res.append(res_max) # 记录每一层的最大值
return res
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def countNodes(self, root: TreeNode) -> int:
if not root:return 0
from collections import deque
que=deque([root])
count=0
while que:
for i in range(len(que)):
cur=que.popleft()
count+=1
if cur.left:que.append(cur.left)
if cur.right:que.append(cur.right)
return count
【递归法】
class Solution:
def countNodes(self, root: TreeNode) -> int:
if not root:return 0
leftNum=0 # 需要先定义变量
rightNum=0
if root.left:leftNum = self.countNodes(root.left) #左
if root.right:rightNum = self.countNodes(root.right) #右
treeNum = leftNum + rightNum + 1 #中
return treeNum
二叉树、N叉树的最大、最小深度、高度
104.二叉树的最大深度
【法一】层序遍历
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def maxDepth(self, root: TreeNode) -> int:
if not root:return 0
from collections import deque
que=deque([root])
length=0
while que:
for i in range(len(que)):
cur=que.popleft()
if cur.left:que.append(cur.left)
if cur.right:que.append(cur.right)
length+=1
return length
【法二】递归法
class Solution:
def maxDepth(self, root: TreeNode) -> int:
if not root:return 0
leftdepth=self.maxDepth(root.left)
rightdepth=self.maxDepth(root.right)
max_depth=1+max(leftdepth,rightdepth)
return max_depth
559. N 叉树的最大深度
【法一】递归法
"""
# Definition for a Node.
class Node:
def __init__(self, val=None, children=None):
self.val = val
self.children = children
"""
class Solution:
def maxDepth(self, root: 'Node') -> int:
if not root:return 0
depth=0
for i in range(len(root.children)):
depth=max(depth,self.maxDepth(root.children[i]))
return depth+1
【法二】层序遍历法
class Solution:
def maxDepth(self, root: 'Node') -> int:
if not root:return 0
from collections import deque
que=deque([root])
depth=0
while que:
for i in range(len(que)):
cur=que.popleft()
if cur.children:que.extend(cur.children)
depth+=1
return depth
- 思路:每个结点都记录了树身,如果该结点没有子节点,说明找到了最小深度,否则继续向下遍历。
- 易错点:
【法一】层序遍历法(迭代)
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def minDepth(self, root: TreeNode) -> int:
if not root:return 0
from collections import deque
que=deque([(root,1)]) # 每个结点都记录了其对应的树深,之后根据其是否还有子树判断能否作为最小深度
while que:
for i in range(len(que)):
cur,depth=que.popleft()
# 如果该树没有子树,则找到最小深度,否则继续往下走
if not cur.left and not cur.right:return depth
if cur.left:que.append((cur.left,depth+1))
if cur.right:que.append((cur.right,depth+1))
return depth
【法二】递归
class Solution:
def minDepth(self, root: TreeNode) -> int:
if not root:return 0
elif not root.left and not root.right:return 1
min_depth = 10**9 # 用10**9比用math.inf快很多
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
110.平衡二叉树
二叉树的深度和高度有很大区别
- 二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数。
- 二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数。
【递归法】
先求高度再判断是否平衡,平衡二叉树则返回高度,不平衡则返回-1
class Solution:
def isBalanced(self, root: TreeNode) -> bool:
# 只要三种不平衡的情况都不是,则是平衡二叉树
if self.get_height(root) != -1:return True
else:return False
# 平衡二叉树则返回高度,不平衡则返回-1
def get_height(self, root: TreeNode) -> int:
if not root:return 0
left_height = self.get_height(root.left)
right_height = self.get_height(root.right)
# 不平衡的三种情况:只要有结点不平衡就不平衡
## 左结点的子节点存在不平衡
if left_height== -1:return -1 # 左 # if (left_height := self.get_height(root.left)) == -1
## 右结点的子节点存在不平衡
elif right_height== -1:return -1 # 右
## 当前左右结点不平衡
elif abs(left_height - right_height) > 1:return -1 # 中
# 平衡,返回树的高度
else:return 1 + max(left_height, right_height)
填充指针
# 层序遍历解法
class Solution:
def connect(self, root: 'Node') -> 'Node':
if not root:return None
queue = [root]
while queue:
n = len(queue)
for i in range(n):
node = queue.pop(0)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
if i == n - 1:break # 如果是每层的最后一个就指向null
node.next = queue[0] # 如果不是每层的最后一个,就指向它的后一个元素
return root
# 链表解法
class Solution:
def connect(self, root: 'Node') -> 'Node':
first = root
while first:
cur = first
while cur: # 遍历每一层的节点
if cur.left: cur.left.next = cur.right # 找左节点的next
if cur.right and cur.next: cur.right.next = cur.next.left # 找右节点的next
cur = cur.next # cur同层移动到下一节点
first = first.left # 从本层扩展到下一层
return root
"""
# Definition for a Node.
class Node:
def __init__(self, val: int = 0, left: 'Node' = None, right: 'Node' = None, next: 'Node' = None):
self.val = val
self.left = left
self.right = right
self.next = next
"""
class Solution:
def connect(self, root: 'Node') -> 'Node':
if not root:return
from collections import deque
que=deque([root])
while que:
size=len(que)
for i in range(size):
cur=que.popleft()
if cur.left:que.append(cur.left)
if cur.right:que.append(cur.right)
if i==size-1:break
cur.next=que[0]
return root
二、反转、对称
这道题目使用前序遍历和后序遍历都可以,唯独中序遍历不方便,因为中序遍历会把某些节点的左右孩子翻转了两次!
226. 翻转二叉树
【法一】递归法:前序遍历
class Solution:
def invertTree(self, root: TreeNode) -> TreeNode:
if not root:
return None
root.left, root.right = root.right, root.left #中
self.invertTree(root.left) #左
self.invertTree(root.right) #右
return root
【法二】迭代法:深度优先遍历(前序遍历)
class Solution:
def invertTree(self, root: TreeNode) -> TreeNode:
# 栈:先进后出,前序遍历的顺序为中左右,故入栈顺序为中右左
if not root:return
stack=[root]
while stack:
cur=stack.pop()
cur.left,cur.right=cur.right,cur.left
if cur.left:stack.append(cur.left)
if cur.right:stack.append(cur.right)
return root
【法三】迭代法:广度优先遍历(层序遍历)
class Solution:
def invertTree(self, root: TreeNode) -> TreeNode:
if not root:return
from collections import deque
que=deque([root])
while que:
for i in range(len(que)):
cur=que.popleft()
cur.left,cur.right=cur.right,cur.left
if cur.left:que.append(cur.left)
if cur.right:que.append(cur.right)
return root
101. 对称二叉树
【法一】递归法
- 递归三部曲:写总函数——(1)确定递归函数的参数和返回值写子函数——(2)确定终止条件:比如两个结点为空的情况(3)确定单层递归的逻辑
- 这道题实际是判断左右结点的内外侧元素值是否相等
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
# 总函数
def isSymmetric(self, root: TreeNode) -> bool:
if not root:return True
return self.compare(root.left,root.right)
# 子函数
def compare(self,left,right):
#首先排除空节点的情况
if not left and not right :return True
elif not left and right :return False
elif left and not right :return False
#排除了空节点,再排除数值不相同的情况
elif left.val!=right.val :return False
#此时就是:左右节点都不为空,且数值相同的情况
#此时才做递归,做下一层的判断
#判断外层相等+内层相等
outside=self.compare(left.left,right.right)
inside=self.compare(left.right,right.left)
same=inside and outside
return same
【法二】迭代法: 使用队列,先进先出
class Solution:
def isSymmetric(self, root: TreeNode) -> bool:
if not root:return True
from collections import deque
que=deque()
que.append(root.left)
que.append(root.right)
while que:
leftnode=que.popleft()
rightnode=que.popleft()
if not leftnode and not rightnode:continue
elif not leftnode and rightnode:return False
elif not rightnode and leftnode:return False
elif leftnode.val!=rightnode.val:return False
que.append(leftnode.left)
que.append(rightnode.right)
que.append(leftnode.right)
que.append(rightnode.left)
return True
【法二】迭代法: 使用栈,先进后出
class Solution:
def isSymmetric(self, root: TreeNode) -> bool:
if not root:return True
stack=[]
stack.append(root.left)
stack.append(root.right)
while stack:
rightnode=stack.pop()
leftnode=stack.pop()
if not rightnode and not leftnode:continue # 说明这次检查到的对称点是对称的,比如外侧都是空
elif not rightnode and leftnode:return False
elif not leftnode and rightnode:return False
elif leftnode.val!=rightnode.val:return False
# 排除以上情况,就继续向下遍历
stack.append(leftnode.left)
stack.append(rightnode.right)
stack.append(leftnode.right)
stack.append(rightnode.left)
return True
100. 相同的树
【法一】迭代法,栈
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
stack=[]
stack.extend([p,q])
while stack:
righttree=stack.pop()
lefttree=stack.pop()
if not righttree and not lefttree:continue
elif not righttree and lefttree:return False
elif not lefttree and righttree:return False
elif lefttree.val!=righttree.val:return False
stack.append(lefttree.left)
stack.append(righttree.left)
stack.append(lefttree.right)
stack.append(righttree.right)
return True
【法二】递归法
class Solution:
def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
if not p and not q:return True
elif not p or not q:return False
elif p.val!=q.val:return False
return self.isSameTree(p.left,q.left) and self.isSameTree(p.right,q.right)
572. 另一棵树的子树
【递归法】
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isSubtree(self, s: TreeNode, t: TreeNode) -> bool:
if not t and not s:return True
elif not t or not s:return False
return self.isSame(s,t) or self.isSubtree(s.left,t) or self.isSubtree(s.right,t)
def isSame(self,p,q):
if not p and not q:return True
elif not p or not q:return False
elif p.val!=q.val:return False
return p.val==q.val and self.isSame(p.left,q.left) and self.isSame(p.right,q.right)