- 层序遍历:本质是BFS.
102. 二叉树的层序遍历
- 思路
- example
- 迭代法。FIFO,用队列deque存储遍历节点。
- 复杂度. 时间:O(n), 空间: O(n)
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
res = []
que = collections.deque()
if root: # !!!
que.append(root)
while que:
size = len(que)
temp = []
for _ in range(size):
node = que.popleft()
temp.append(node.val)
if node.left:
que.append(node.left)
if node.right:
que.append(node.right)
res.append(temp)
return res
- 递归写法,本质是DFS, 前序遍历。
- 用depth标记层数(深度)
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
res = []
def dfs(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:
dfs(root.left, depth + 1) # process child nodes for the next depth
if root.right:
dfs(root.right, depth + 1)
dfs(root, 0)
return res
107. 二叉树的层序遍历 II
- 思路
- example
- 层序遍历,最后一步反转即可: res.reverse()
- 或者用stack,按照右左顺序入栈。
- 复杂度. 时间:O(n), 空间: O(n)
class Solution:
def levelOrderBottom(self, root: Optional[TreeNode]) -> List[List[int]]:
res = []
que = collections.deque()
if root:
que.append(root)
while que:
size = len(que)
temp = []
for _ in range(size):
node = que.popleft()
temp.append(node.val)
if node.left:
que.append(node.left)
if node.right:
que.append(node.right)
res.append(temp)
res.reverse()
return res
199. 二叉树的右视图
- 思路
- example
- 层序遍历,取每一层最后一个数字即可。
- 复杂度. 时间:O(n), 空间: O(n)
class Solution:
def rightSideView(self, root: Optional[TreeNode]) -> List[int]:
if root == None:
return []
res = []
que = collections.deque([root])
while que:
size = len(que)
for i in range(size):
node = que.popleft()
if i == size - 1:
res.append(node.val)
if node.left:
que.append(node.left)
if node.right:
que.append(node.right)
return res
class Solution:
def rightSideView(self, root: Optional[TreeNode]) -> List[int]:
res = []
que = collections.deque()
if root:
que.append(root)
while que:
size = len(que)
temp = []
for _ in range(size):
node = que.popleft()
temp.append(node.val)
if node.left:
que.append(node.left)
if node.right:
que.append(node.right)
res.append(temp[-1])
return res
637. 二叉树的层平均值
- 思路
- example
- 层序遍历,每层计算平均值。
- 复杂度. 时间:O(n), 空间: O(n)
class Solution:
def averageOfLevels(self, root: Optional[TreeNode]) -> List[float]:
res = []
if root:
que = collections.deque([root])
while que:
size = len(que)
sum_ = 0
for _ in range(size):
node = que.popleft()
sum_ += node.val
if node.left:
que.append(node.left)
if node.right:
que.append(node.right)
res.append(sum_ / size)
return res
429. N 叉树的层序遍历
- 思路
- example
- 层序遍历,多个children
- 复杂度. 时间:O(n), 空间: O(n)
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]]:
res = []
que = collections.deque()
if root:
que.append(root)
while que:
size = len(que)
temp = []
for _ in range(size):
node = que.popleft()
temp.append(node.val)
for child in node.children:
if child:
que.append(child)
res.append(temp)
return res
515. 在每个树行中找最大值
- 思路
- example
- 层序遍历,每层求最大值。
- 复杂度. 时间:O(n), 空间: O(n)
class Solution:
def largestValues(self, root: Optional[TreeNode]) -> List[int]:
res = []
que = collections.deque()
if root:
que.append(root)
while que:
size = len(que)
max_ = -float('inf')
for _ in range(size):
node = que.popleft()
max_ = max(max_, node.val)
if node.left:
que.append(node.left)
if node.right:
que.append(node.right)
res.append(max_)
return res
116. 填充每个节点的下一个右侧节点指针
- 思路
- example
- 完美二叉树: 所有叶子节点都在同一层,每个父节点都有两个子节点.
- 层序遍历,当前节点.next = que[0] if i != size - 1. 避免使用pre指针。
- 维护pre指针亦可
- 复杂度. 时间:O(n), 空间: O(n)
class Solution:
def connect(self, root: 'Optional[Node]') -> 'Optional[Node]':
que = collections.deque()
if root:
que.append(root)
while que:
size = len(que)
for i in range(size):
node = que.popleft()
if i != size - 1:
node.next = que[0]
else:
node.next = None
if node.left:
que.append(node.left)
if node.right:
que.append(node.right)
return root
-
进阶: 空间, 链表解法
- 注意每个节点默认的next为None
利用next遍历每一层节点
利用left,right链接下一层的节点
first: 每层的第一个节点
class Solution:
def connect(self, root: 'Optional[Node]') -> 'Optional[Node]':
first = root
while first:
cur = first
while cur: # 遍历每一层节点
if cur.left: # 左节点next=cur.right
cur.left.next = cur.right
if cur.right and cur.next: # 右节点next=cur.next.left
cur.right.next = cur.next.left
cur = cur.next # 同层节点
first = first.left # 下一层起始节点
return root
- 更一般的写法 (可推广至II)
cur: 上级指针,上层已链接好
pre:下层pre指针
class Solution:
def connect(self, root: 'Optional[Node]') -> 'Optional[Node]':
first = root
while first: # first: first node in the current level
cur = first
dummyhead = Node(-1)
pre = dummyhead
while cur: # traverse node in the current level
if cur.left:
pre.next = cur.left
pre = cur.left
if cur.right:
pre.next = cur.right
pre = cur.right
cur = cur.next
first = dummyhead.next
return root
class Solution:
def connect(self, root: 'Optional[Node]') -> 'Optional[Node]':
if root == None:
return root
cur = root
while cur:
dummyhead = Node(-1,None,None,None)
pre = dummyhead
while cur:
if cur.left:
pre.next = cur.left
pre = cur.left
if cur.right:
pre.next = cur.right
pre = cur.right
cur = cur.next
cur = dummyhead.next
return root
117. 填充每个节点的下一个右侧节点指针 II
- 思路
- example
- 普通二叉树.
- 迭代写法与上一题没有区别。
- 复杂度. 时间:O(n), 空间: O(n)
class Solution:
def connect(self, root: 'Node') -> 'Node':
if root == None:
return None
que = collections.deque([root])
while que:
size = len(que)
for i in range(size):
node = que.popleft()
if i != size - 1:
node.next = que[0]
else:
node.next = None
if node.left:
que.append(node.left)
if node.right:
que.append(node.right)
return root
- 进阶: 空间
- 链表解法,使用dummyhead
-
使用pre指针 来链接下一层Node (cur和pre是相邻两层的移动指标)
- 参考
class Solution:
def connect(self, root: 'Node') -> 'Node':
if root == None:
return None
first = root
while first: # 遍历每一层
cur = first
dummyhead = Node(0)
pre = dummyhead
while cur: # 链接下一层
if cur.left:
pre.next = cur.left
pre = pre.next
if cur.right:
pre.next = cur.right
pre = pre.next
cur = cur.next # first-node 同层其它node
first = dummyhead.next # 下一层first-node
return root
class Solution:
def connect(self, root: 'Node') -> 'Node':
if root == None:
return None
cur = root
while cur:
dummyhead = Node(0, None, None, None) # next pointer must be None because it could point to cur.right
pre = dummyhead
while cur:
if cur.left:
pre.next = cur.left
pre = cur.left
if cur.right:
pre.next = cur.right
pre = cur.right
cur = cur.next
cur = dummyhead.next
return root
104. 二叉树的最大深度
- 思路
- example
- 层序 bfs
- 复杂度. 时间:O(n), 空间: O(n)
class Solution:
def maxDepth(self, root: Optional[TreeNode]) -> int:
level = 0
que = collections.deque()
if root:
que.append(root)
while que:
size = len(que)
level += 1
for _ in range(size):
node = que.popleft()
if node.left:
que.append(node.left)
if node.right:
que.append(node.right)
return level
- dfs亦可
111. 二叉树的最小深度
- 思路
- example
- 层序遍历
- 复杂度. 时间:O(n), 空间: O(n)
class Solution:
def minDepth(self, root: Optional[TreeNode]) -> int:
res = 0
que = collections.deque()
if root:
que.append(root)
while que:
size = len(que)
res += 1
for _ in range(size):
node = que.popleft()
if node.left == None and node.right == None:
return res
if node.left:
que.append(node.left)
if node.right:
que.append(node.right)
return 0
- DFS亦可以。
TBA
226. 翻转二叉树
- 思路
- example
- 递归,后序遍历
- 复杂度. 时间:O(n), 空间: O(n)
class Solution:
def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
def traversal(root):
if root == None:
return None
new_left = traversal(root.left)
new_right = traversal(root.right)
root.left = new_right
root.right = new_left
return root
return traversal(root)
class Solution:
def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
if root == None:
return root
left = self.invertTree(root.left)
right = self.invertTree(root.right)
root.left = right
root.right = left
return root
- 前序遍历,迭代写法。
- 交换左右子节点。
class Solution:
def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
if root == None:
return None
stack = [root]
while stack:
node = stack.pop()
node.left, node.right = node.right, node.left
if node.right:
stack.append(node.right)
if node.left:
stack.append(node.left)
return root
- 层序遍历(迭代)也可以。
- 交换左右子节点。
class Solution:
def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
if root == None:
return None
que = collections.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
101. 对称二叉树
- 思路
- example
- 本质:比较两棵子树。
- node1.val vs node2.val
- node1.left vs node2.right, node1.right vs node2.left
- 递归:前序后序遍历混合
- 注意base case的分类。
- 复杂度. 时间:O(n), 空间: O(n)
class Solution:
def isSymmetric(self, root: Optional[TreeNode]) -> bool:
def traversal(left, right):
if left == None and right == None:
return True
if left != None and right == None:
return False
if left == None and right != None:
return False
if left.val != right.val:
return False
return traversal(left.right, right.left) and traversal(left.left, right.right)
if root == None:
return True
return traversal(root.left, root.right)
class Solution:
def isSymmetric(self, root: Optional[TreeNode]) -> bool:
def traverse(left_node, right_node):
if left_node == None and right_node == None:
return True
if left_node == None or right_node == None:
return False
if left_node.val != right_node.val:
return False
return traverse(left_node.right, right_node.left) and traverse(left_node.left, right_node.right)
return traverse(root.left, root.right)
- DFS用迭代实现: 一次加入两个对应的node进行比较。
- 队列 (TBA)
- 栈 (见下面)
- 空指针入栈,方便比较。
class Solution:
def isSymmetric(self, root: Optional[TreeNode]) -> bool:
if root == None:
return True
stack = [root.left, root.right]
while stack:
right = stack.pop()
left = stack.pop()
if left == None and right != None: return False
if left != None and right == None: return False
if left == None and right == None: continue
if left.val != right.val: return False
stack.append(left.left)
stack.append(right.right)
stack.append(left.right)
stack.append(right.left)
return True
- BFS 层序遍历实现也可以
- 每一层对称
TBA