二叉树的统一迭代法
那我们就将访问的节点放入栈中,把要处理的节点也放入栈中但是要做标记。
如何标记呢,就是要处理的节点放入栈之后,紧接着放入一个空指针作为标记。 这种方法也可以叫做标记法。
可以看出我们将访问的节点直接加入到栈中,但如果是处理的节点则后面放入一个空节点, 这样只有空节点弹出的时候,才将下一个节点放进结果集。
迭代法前序遍历:
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
result = []
st= []
if root:
st.append(root)
while st:
node = st.pop()
if node != None:
if node.right: #右
st.append(node.right)
if node.left: #左
st.append(node.left)
st.append(node) #中
st.append(None)
else:
node = st.pop()
result.append(node.val)
return result
迭代法中序遍历:
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
result = []
st = []
if root:
st.append(root)
while st:
node = st.pop()
if node != None:
if node.right: #添加右节点(空节点不入栈)
st.append(node.right)
st.append(node) #添加中节点
st.append(None) #中节点访问过,但是还没有处理,加入空节点做为标记。
if node.left: #添加左节点(空节点不入栈)
st.append(node.left)
else: #只有遇到空节点的时候,才将下一个节点放进结果集
node = st.pop() #重新取出栈中元素
result.append(node.val) #加入到结果集
return result
迭代法后序遍历:
class Solution:
def postorderTraversal(self, root: TreeNode) -> List[int]:
result = []
st = []
if root:
st.append(root)
while st:
node = st.pop()
if node != None:
st.append(node) #中
st.append(None)
if node.right: #右
st.append(node.right)
if node.left: #左
st.append(node.left)
else:
node = st.pop()
result.append(node.val)
return result
二叉树的层序遍历
给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。
需要借用一个辅助数据结构即队列来实现,队列先进先出,符合一层一层遍历的逻辑,而用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。
class Solution:
"""二叉树层序遍历迭代解法"""
def levelOrder(self, root: TreeNode) -> List[List[int]]:
results = []
if not root:
return results
from collections import deque
que = deque([root])
while que:
size = len(que)
result = []
for _ in range(size):
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
二叉树的层次遍历 II
给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
相对于102.二叉树的层序遍历,就是最后把result数组反转一下就可以了。
class Solution:
"""二叉树层序遍历II迭代解法"""
def levelOrderBottom(self, root: TreeNode) -> List[List[int]]:
results = []
if not root:
return results
from collections import deque
que = deque([root])
while que:
result = []
for _ 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)
results.reverse()
return results
二叉树的右视图
给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
思路:
层序遍历的时候,判断是否遍历到单层的最后面的元素,如果是,就放进result数组中,随后返回result就可以了。
class Solution:
def rightSideView(self, root: TreeNode) -> List[int]:
if not root:
return []
# deque来自collections模块,不在力扣平台时,需要手动写入
# 'from collections import deque' 导入
# deque相比list的好处是,list的pop(0)是O(n)复杂度,deque的popleft()是O(1)复杂度
quene = deque([root])
out_list = []
while quene:
# 每次都取最后一个node就可以了
node = quene[-1]
out_list.append(node.val)
# 执行这个遍历的目的是获取下一层所有的node
for _ in range(len(quene)):
node = quene.popleft()
if node.left:
quene.append(node.left)
if node.right:
quene.append(node.right)
return out_list
二叉树的层平均值
给定一个非空二叉树, 返回一个由每层节点平均值组成的数组。
思路:
本题就是层序遍历的时候把一层求个总和在取一个均值。
class Solution:
"""二叉树层平均值迭代解法"""
def averageOfLevels(self, root: TreeNode) -> List[float]:
results = []
if not root:
return results
from collections import deque
que = deque([root])
while que:
size = len(que)
sum_ = 0
for _ 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
N叉树的层序遍历
给定一个 N 叉树,返回其节点值的层序遍历。 (即从左到右,逐层遍历)。
例如,给定一个 3叉树 :
返回其层序遍历:
[ [1], [3,2,4], [5,6] ]
思路:
这道题依旧是模板题,只不过一个节点有多个孩子了
class Solution:
"""N叉树的层序遍历迭代法"""
def levelOrder(self, root: 'Node') -> List[List[int]]:
results = []
if not root:
return results
from collections import deque
que = deque([root])
while que:
result = []
for _ in range(len(que)):
cur = que.popleft()
result.append(cur.val)
# cur.children 是 Node 对象组成的列表,也可能为 None
if cur.children:
que.extend(cur.children)
results.append(result)
return results
在每个树行中找最大值
您需要在二叉树的每一行中找到最大的值。
思路:
层序遍历,取每一层的最大值
class Solution:
def largestValues(self, root: Optional[TreeNode]) -> List[int]:
if not root:
return []
results = []
que = deque([root])
while que:
in_list = []
for _ in range(len(que)):
cur = que.popleft()
in_list.append(cur.val)
if cur.left:
que.append(cur.left)
if cur.right:
que.append(cur.right)
results.append(max(in_list))
return results
填充每个节点的下一个右侧节点指针
给定一个完美二叉树,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。
初始状态下,所有 next 指针都被设置为 NULL。
思路:
本题依然是层序遍历,只不过在单层遍历的时候记录一下本层的头部节点,然后在遍历的时候让前一个节点指向本节点就可以了
"""
# 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:
n = len(que)
for i in range(n):
node = que.popleft()
if node.left:
que.append(node.left)
if node.right:
que.append(node.right)
if i == n - 1:
break
node.next = que[0]
return root
填充每个节点的下一个右侧节点指针II
思路:
这道题目说是二叉树,但116题目说是完整二叉树,其实没有任何差别,一样的代码一样的逻辑一样的味道
class Solution:
def connect(self, root: 'Node') -> 'Node':
if not root:
return None
que = deque([root])
while que:
tail = None
for _ in range(len(que)):
cur = que.popleft()
if cur.left:
que.append(cur.left)
if cur.right:
que.append(cur.right)
if tail:
tail.next = cur
tail = cur
return root
二叉树的最大深度
给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明: 叶子节点是指没有子节点的节点。
示例:
给定二叉树 [3,9,20,null,null,15,7],
返回它的最大深度 3 。
思路:
使用迭代法的话,使用层序遍历是最为合适的,因为最大的深度就是二叉树的层数,和层序遍历的方式极其吻合。
在二叉树中,一层一层的来遍历二叉树,记录一下遍历的层数就是二叉树的深度.
class Solution:
def maxDepth(self, root: Optional[TreeNode]) -> int:
if not root:
return 0
que = deque([root])
depth = 0
while que:
for _ in range(len(que)):
cur = que.popleft()
if cur.left:
que.append(cur.left)
if cur.right:
que.append(cur.right)
depth += 1
return depth
二叉树的最小深度
相对于 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 minDepth(self, root: Optional[TreeNode]) -> int:
if not root:
return 0
que = deque([(root, 1)])
while que:
cur, depth = que.popleft()
if cur.left == None and cur.right == None:
return depth
if cur.left:
que.append((cur.left, depth + 1))
if cur.right:
que.append((cur.right, depth + 1))
return 0
翻转二叉树
翻转一棵二叉树。
把每一个节点的左右孩子交换一下
class Solution:
def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
if not root:
return root
que = deque([root])
while que:
for _ 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