102.二叉树的层序遍历
层序遍历一个二叉树,即从左到右一层一层的去遍历二叉树,需要借用一个辅助数据结构即队列来实现,队列先进先出,符合一层一层遍历的逻辑;而用栈先进后出,适合模拟深度优先遍历也就是递归的逻辑。这种层序遍历方式就是图论中的广度优先遍历,只不过我们应用在二叉树上。
法一:迭代法
# 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 levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
if not root:
return []
que = deque([root])
# que.append(root)
res = []
while que:
size = len(que)
vector = []
while size > 0:
node = que.popleft()
vector.append(node.val)
if node.left:
que.append(node.left)
if node.right:
que.append(node.right)
size -= 1
res.append(vector)
return res
法二:递归
# 递归法
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
res = []
def helper(root, depth):
if not root: return []
if len(res) == depth: res.append([]) # start the current depth
res[depth].append(root.val) # fulfil the current depth
if root.left: helper(root.left, depth + 1) # process child nodes for the next depth
if root.right: helper(root.right, depth + 1)
helper(root, 0)
return res
能理解,但自己想不到
-
- 二叉树的层序遍历 II
自底向上从左至右返回层序遍历的值,则只需返回上述code里的 res[::-1] 即可
- 二叉树的层序遍历 II
-
- 二叉树的右视图
给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
- 二叉树的右视图
# 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: Optional[TreeNode]) -> List[int]:
if not root:
return []
res = []
que = deque([root])
while que:
size = len(que)
vector = []
for _ in range(size):
node = que.popleft()
vector.append(node.val)
if node.left:
que.append(node.left)
if node.right:
que.append(node.right)
res.append(vector[-1]) # 只需将这一步改为添加每层遍历得到的数组最右边的值到res数组里
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 averageOfLevels(self, root: Optional[TreeNode]) -> List[float]:
if not root:
return []
res = []
que = deque([root])
while que:
size = len(que)
# vector = []
total = 0
for _ in range(size):
node = que.popleft()
total += node.val # 将数组改为求和,不改也可以,下面res.append(mean(vector)即可
# vector.append(node.val)
if node.left:
que.append(node.left)
if node.right:
que.append(node.right)
res.append(total / size) # 求每层结点值的平均值即可
return res
-
- N 叉树的层序遍历
给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)。
树的序列化输入是用层序遍历,每组子节点都由 null 值分隔(参见示例)。
"""
# 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]]:
if not root:
return []
res = []
que = deque([root])
while que:
size = len(que)
vector = []
for _ in range(size):
node = que.popleft()
vector.append(node.val)
if node.children:
que.extend(node.children) # 唯一的区别就是二叉树分左右孩子,而N叉树用children,可能为null,可能为一个列表
res.append(vector)
return res
-
- 在每个树行中找最大值
给定一棵二叉树的根节点 root ,请找出该二叉树中每一层的最大值。
# 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: Optional[TreeNode]) -> List[int]:
if not root:
return []
res = []
que = deque([root])
while que:
size = len(que)
vector = []
for _ in range(size):
node = que.popleft()
vector.append(node.val)
if node.left:
que.append(node.left)
if node.right:
que.append(node.right)
res.append(max(vector)) # 添加最大值即可
return res
-
- 填充每个节点的下一个右侧节点指针
给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
- 填充每个节点的下一个右侧节点指针
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。
初始状态下,所有 next 指针都被设置为 NULL。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/populating-next-right-pointers-in-each-node
此题不需要额外的数组(类似上述代码里res和vector)存储结果,直接在root上做改变的,返回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: 'Optional[Node]') -> 'Optional[Node]':
if not root:
return None
que = deque([root])
while que:
size = len(que)
for i in range(size):
node = que.popleft()
if node.left:
que.append(node.left)
if node.right:
que.append(node.right)
if i == size - 1:
break
node.next = que[0] # 弹出node,此时que[0]即为node的右兄弟
return root
-
- 填充每个节点的下一个右侧节点指针 II
和上一题解法一模一样,无所谓是二叉树还是完美二叉树
- 填充每个节点的下一个右侧节点指针 II
-
- 二叉树的最大深度
给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明: 叶子节点是指没有子节点的节点。
- 二叉树的最大深度
# 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: Optional[TreeNode]) -> int:
if not root:
return 0
count = 0 # 记录层数
que = deque([root])
while que:
size = len(que)
# vector = []
for i in range(size):
node = que.popleft()
# vector.append(node)
if node.left:
que.append(node.left)
if node.right:
que.append(node.right)
count += 1
return count
-
- 二叉树的最小深度
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
- 二叉树的最小深度
# 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: Optional[TreeNode]) -> int:
if not root:
return 0
count = 0 # 记录层数
que = deque([root])
while que:
size = len(que)
# vector = []
for i in range(size):
node = que.popleft()
# vector.append(node)
if (not node.left) and (not node.right):
return count + 1 # 一旦我遍历到的node无左右孩子,直接返回 count+1
if node.left:
que.append(node.left)
if node.right:
que.append(node.right)
count += 1
return count
226. 翻转二叉树
给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。
法一:层序遍历时交换左右指针
# 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 invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
if not root:
return None
que = deque([root])
while que:
size = len(que)
for _ in range(size):
node = que.popleft()
node.left, node.right = node.right, node.left # 在这里交换左右指针即可,其他同层序遍历
if node.left:
que.append(node.left)
if node.right:
que.append(node.right)
return root
法二:递归
# 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 invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
if not root:
return root
root.left, root.right = root.right, root.left # 中
self.invertTree(root.left) # 左
self.invertTree(root.right) # 右
return root
# 后序
# self.invertTree(root.left) # 左
# self.invertTree(root.right) # 右
# root.left, root.right = root.right, root.left # 中
# 中序
class Solution:
def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
if not root:
return root
self.invertTree(root.left) # 左
root.left, root.right = root.right, root.left # 中
self.invertTree(root.left) # 右 # 因为在递归左子树时已经交换过左右了,此时递归的右子树就变成交换之前的左子树了
# 所以就要交换之前的右子树,即现在的左子树
return root
法三:前序遍历用的迭代法 用栈模拟
class Solution:
def invertTree(self, root: TreeNode) -> TreeNode:
if not root:
return root
st = []
st.append(root)
while st:
node = st.pop()
node.left, node.right = node.right, node.left #中
if node.right:
st.append(node.right) #右
if node.left:
st.append(node.left) #左
return root
101. 对称二叉树
这道题理解code略有点难,需要好好推一推
# 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: Optional[TreeNode]) -> bool:
if not root:
return True
return self.compare(root.left, root.right)
# 传入参数是根结点的左右子树,因为比较的是左右子树是否可以互相翻转
def compare(self, left, right):
# 首先排除空节点的情况
if left == None and right != None: return False
elif left != None and right == None: return False
elif left == None and right == None: return True
# 排除非空 但左右值不等
elif left.val != right.val: return False
#此时就是:左右节点都不为空,且数值相同的情况
#此时才做递归,做下一层的判断
outside = self.compare(left.left, right.right) #左子树:左、 右子树:右
inside = self.compare(left.right, right.left) #左子树:右、 右子树:左
isSame = outside and inside #左子树:中、 右子树:中 (逻辑处理)
return isSame
- 也可以使用迭代法
# 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
import collections
class Solution:
def isSymmetric(self, root: TreeNode) -> bool:
if not root:
return True
queue = collections.deque()
queue.append(root.left) #将左子树头结点加入队列
queue.append(root.right) #将右子树头结点加入队列
while queue: #接下来就要判断这这两个树是否相互翻转
leftNode = queue.popleft()
rightNode = queue.popleft()
if not leftNode and not rightNode: #左节点为空、右节点为空,此时说明是对称的
continue
#左右一个节点不为空,或者都不为空但数值不相同,返回false
if not leftNode or not rightNode or leftNode.val != rightNode.val:
return False
queue.append(leftNode.left) #加入左节点左孩子
queue.append(rightNode.right) #加入右节点右孩子
queue.append(leftNode.right) #加入左节点右孩子
queue.append(rightNode.left) #加入右节点左孩子
return True