- 層序遍歷:本質(zhì)是BFS.
102. 二叉樹的層序遍歷
- 思路
- example
- 迭代法份企。FIFO,用隊列deque存儲遍歷節(jié)點。
- 復雜度. 時間: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
- 遞歸寫法睹栖,本質(zhì)是DFS, 前序遍歷惠赫。
- 用depth標記層數(shù)(深度)
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
- 層序遍歷鞍匾,最后一步反轉(zhuǎn)即可: 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
- 層序遍歷愁拭,取每一層最后一個數(shù)字即可讲逛。
- 復雜度. 時間: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. 填充每個節(jié)點的下一個右側(cè)節(jié)點指針
- 思路
- example
- 完美二叉樹: 所有葉子節(jié)點都在同一層许赃,每個父節(jié)點都有兩個子節(jié)點.
- 層序遍歷,當前節(jié)點.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
-
進階: 空間, 鏈表解法
- 注意每個節(jié)點默認的next為None
利用next遍歷每一層節(jié)點
利用left,right鏈接下一層的節(jié)點
first: 每層的第一個節(jié)點
class Solution:
def connect(self, root: 'Optional[Node]') -> 'Optional[Node]':
first = root
while first:
cur = first
while cur: # 遍歷每一層節(jié)點
if cur.left: # 左節(jié)點next=cur.right
cur.left.next = cur.right
if cur.right and cur.next: # 右節(jié)點next=cur.next.left
cur.right.next = cur.next.left
cur = cur.next # 同層節(jié)點
first = first.left # 下一層起始節(jié)點
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. 填充每個節(jié)點的下一個右側(cè)節(jié)點指針 II
- 思路
- example
- 普通二叉樹.
- 迭代寫法與上一題沒有區(qū)別。
- 復雜度. 時間: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. 翻轉(zhuǎn)二叉樹
- 思路
- 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
- 前序遍歷沟于,迭代寫法咳胃。
- 交換左右子節(jié)點。
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
- 層序遍歷(迭代)也可以社裆。
- 交換左右子節(jié)點拙绊。
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
- 本質(zhì):比較兩棵子樹。
- 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用迭代實現(xiàn): 一次加入兩個對應(yīng)的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 層序遍歷實現(xiàn)也可以
- 每一層對稱
TBA