Okii's blog

仅作为记录自己的学习过程

0%

Leetcode 二叉树遍历篇

Leetcode刷题记录——二叉树遍历篇

递归

  1. 确定递归函数的参数和返回值: 确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。
  2. 确定终止条件: 写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。
  3. 确定单层递归的逻辑: 确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。

Leetcode144 二叉树的前序遍历

Python代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 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 preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
# 先定义一个要返回的result列表
result = []
# 将根节点、result传入preTraversal函数, 该函数负责递归调用
self.preTraversal(root, result)
return result

def preTraversal(self, root: Optional[TreeNode], result):
# 终止条件的确定, 如果当前节点为空, 则返回
if not root:
return
# 确定单层递归的逻辑,前序是根左右
result.append(root.val)
self.preTraversal(root.left, result)
self.preTraversal(root.right, result)

Leetcode145 二叉树的后序遍历

Python代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 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 postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
result = []
self.postTraversal(root, result)
return result
def postTraversal(self, root: Optional[TreeNode], result):
if not root:
return
self.postTraversal(root.left, result)
self.postTraversal(root.right, result)
result.append(root.val)

Leetcode94 二叉树的中序遍历

Python代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 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 inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
result = []
self.inTraversal(root, result)
return result
def inTraversal(self, root: Optional[TreeNode], result):
if not root:
return
self.inTraversal(root.left, result)
result.append(root.val)
self.inTraversal(root.right, result)

非递归方法(迭代法)

递归的实现其实也是栈,而迭代法是显示的用栈的操作去实现树的遍历

Leetcode144 二叉树的前序遍历

Python代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 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 preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
if not root:
return []
stack = [root]
res = []
while stack:
node = stack.pop()
res.append(node.val)
# 因为后进先出 所以右孩子入栈
if node.right:
stack.append(node.right)
if node.left:
stack.append(node.left)
return res

Leetcode145 二叉树的后序遍历

Python代码如下:

前序遍历:根左右

后序遍历:左右根

将前序变成—>根右左,最后的res再反转一下就是左右根

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 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 postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
if not root:
return []
stack = [root]
res = []
while stack:
node = stack.pop()
res.append(node.val)
if node.left:
stack.append(node.left)
if node.right:
stack.append(node.right)
return res[::-1]

Leetcode94 二叉树的中序遍历

Python代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 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 inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
if not root:
return []
stack = []
res = []
# cur指针用作遍历整棵树
cur = root
while cur or stack:
# 先迭代访问到树的最左节点
if cur:
stack.append(cur)
cur = cur.left
# 当到最左时, cur为空
# 此时弹出栈顶元素, res.append(node.val)
# 并将cur指针交给其右孩子继续迭代
else:
node = stack.pop()
res.append(node.val)
cur = node.right
return res

Leetcode102 二叉树的层序遍历

层序遍历就要用到队列的思想,先进先出

Python代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from collections import deque
# 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 []
res = []
queue = deque()
queue.append(root)
while queue:
level = []
# 主要是每一层需要求出当前队列的长度, 即每一层的节点数
for _ in range(len(queue)):
node = queue.popleft()
level.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
res.append(level)
return res

Leetcode107 二叉树的层序遍历Ⅱ

与102一样的思路,要从底下遍历,只要把最后的res反转一下就行

Python代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 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: Optional[TreeNode]) -> List[List[int]]:
if not root:
return []
res = []
queue = deque()
queue.append(root)
while queue:
level = []
for _ in range(len(queue)):
node = queue.popleft()
level.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
res.append(level)
return res[::-1]

Leetcode199 二叉树的右视图

一样的思路,最后res.append(level[-1])

Python代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from collections import deque
# 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 = []
queue = deque()
queue.append(root)
while queue:
level = []
for _ in range(len(queue)):
node = queue.popleft()
level.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
res.append(level[-1])
return res

Leetcode637 二叉树的层平均值

一样的思路,每层求和再求平均即可

Python代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 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 = []
queue = deque()
queue.append(root)
while queue:
sum = 0
length = len(queue)
for _ in range(length):
node = queue.popleft()
sum += node.val
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
mean = sum / length
res.append(mean)
return res

Leetcode429 N叉树的遍历

一样的思路,只是在每个节点处需要遍历该节点的所有children

Python代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
"""
# 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 = []
queue = deque()
queue.append(root)
while queue:
level = []
for _ in range(len(queue)):
node = queue.popleft()
level.append(node.val)
for child in node.children:
queue.append(child)
res.append(level)
return res

Leetcode515 在每个树行中找最大值

一样的思路,只不过要记录最大值

Python代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 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 = []
queue = deque()
queue.append(root)
while queue:
max_val = float('-inf')
for _ in range(len(queue)):
node = queue.popleft()
if node.val > max_val:
max_val = node.val
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
res.append(max_val)
return res

Leetcode116 填充每个节点的下一个右侧节点指针

Python代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
"""
# 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 root
queue = deque()
queue.append(root)
while queue:
# 这里一开始pre = None设置的比较巧妙
pre = None
for _ in range(len(queue)):
node = queue.popleft()
# 以及这里的处理
if pre:
pre.next = node
pre = node
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return root

Leetcode117 填充每个节点的下一个右侧节点指针II

跟116没区别,代码都一样

Leetcode104 二叉树的最大深度

最大的深度就是二叉树的层数,和层序遍历的方式极其吻合。

Python代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 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
queue = deque()
queue.append(root)
depth = 0
while queue:
for _ in range(len(queue)):
node = queue.popleft()
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
depth += 1
return depth

Leetcode111 二叉树的最小深度

只有当左右孩子都为空的时候,才说明遍历的最低点了。如果其中一个孩子为空则不是最低点

Python代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 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
queue = deque()
queue.append(root)
depth = 0
while queue:
depth += 1
for _ in range(len(queue)):
node = queue.popleft()
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
if not node.left and not node.right:
return depth
return depth