- 层序遍历
知识点:python3的deque:https://blog.csdn.net/langb2014/article/details/100118296
模板:
popleft一个节点,append自己的value到level数组中(遍历该层),然后append所有他的子节点到queue中(queue存下一层的节点);将一层的节点都popleft后,将level数组存入res数组(将该层节点值加入结果数组)。
python:
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def levelOrder(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
queue = collections.deque()
if root:
queue.append(root)
res = []
while queue:
size = len(queue)
level = []
for _ in range(size):
cur = queue.popleft()
level.append(cur.val)
if cur.left:
queue.append(cur.left)
if cur.right:
queue.append(cur.right)
res.append(level)
return res
c++
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
queue<TreeNode*> que;
if (root != NULL) que.push(root);
vector<vector<int>> result;
while (!que.empty()) {
int size = que.size();
vector<int> vec;
// 这里一定要使用固定大小size,不要使用que.size(),因为que.size是不断变化的
for (int i = 0; i < size; i++) {
TreeNode* node = que.front();
que.pop();
vec.push_back(node->val);
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
result.push_back(vec);
}
return result;
}
};
- 二叉树的层次遍历 II
给定一个二叉树,返回其节点值自底向上的层次遍历。最后用res.reverse()或者reversed_res = reversed(res)把result数组反转一下就可以了。
Note:reversed()可作用于各种可迭代对象,返回 list_reverseiterator object对象,可用list()转换为list对象。list.reverse()是原地转换,改变原数组。sorted()返回将迭代器中的元素排序的新列表。
class Solution(object):
def levelOrder(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
queue = collections.deque()
if root:
queue.append(root)
res = []
while queue:
size = len(queue)
level = []
for _ in range(size):
cur = queue.popleft()
level.append(cur.val)
if cur.left:
queue.append(cur.left)
if cur.right:
queue.append(cur.right)
res.append(level)
res.reverse() # 反转res
return res
199.二叉树的右视图
给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
层序遍历的时候,判断是否遍历到单层的最后面的元素,如果是,就放进result数组中,随后返回result就可以了。
# 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: TreeNode) -> List[int]:
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
queue = collections.deque()
if root:
queue.append(root)
res = []
while queue:
size = len(queue)
for i in range(size):
cur = queue.popleft()
if i == size - 1: # 判断是否遍历到单层的最后面的元素
res.append(cur.val)
if cur.left:
queue.append(cur.left)
if cur.right:
queue.append(cur.right)
return res
637.二叉树的层平均值
给定一个非空二叉树, 返回一个由每层节点平均值组成的数组。本题就是层序遍历的时候把一层求个总和在取一个均值。
class Solution(object):
def averageOfLevels(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
queue = collections.deque()
if root:
queue.append(root)
res = []
while queue:
size = len(queue)
sum = 0
for i in range(size):
cur = queue.popleft()
sum += cur.val;
if cur.left:
queue.append(cur.left)
if cur.right:
queue.append(cur.right)
res.append(sum / size); # 将每一层均值放进结果集
return res
- N叉树的层序遍历
"""
# 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]]:
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
queue = collections.deque()
if root:
queue.append(root)
res = []
while queue:
size = len(queue)
level = []
for _ in range(size):
cur = queue.popleft()
level.append(cur.val)
for children in cur.children:
if children:
queue.append(children)
res.append(level)
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 largestValues(self, root: TreeNode) -> List[int]:
queue = collections.deque()
if root:
queue.append(root)
res = []
while queue:
size = len(queue)
max_val = float("-inf")
for _ in range(size):
cur = queue.popleft()
if max_val < cur.val:
max_val = cur.val
if cur.left:
queue.append(cur.left)
if cur.right:
queue.append(cur.right)
res.append(max_val)
return res
- 填充每个节点的下一个右侧节点指针 - 完美二叉树(满二叉树)
https://leetcode-cn.com/problems/populating-next-right-pointers-in-each-node/solution/dong-hua-yan-shi-san-chong-shi-xian-116-tian-chong/
1)时间空间复杂度都为O(N)的解法,借助层序遍历:
本题依然是层序遍历,只不过在单层遍历的时候记录一下本层的头部节点,然后在遍历的时候让前一个节点指向本节点就可以了.
"""
# 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: 'Node') -> 'Node':
"""
:type root: Node
:rtype: Node
"""
queue = []
if root:
queue.append(root)
else:
return root
while queue:
size = len(queue)
# 将队列中的元素串联起来
tmp = queue[0]
for i in range(1,size):
tmp.next = queue[i]
tmp = queue[i]
# 遍历队列中的每个元素,将每个元素的左右节点也放入队列中
for _ in range(size):
tmp = queue.pop(0)
if tmp.left:
queue.append(tmp.left)
if tmp.right:
queue.append(tmp.right)
return root
2)时间空间复杂度为O(N)、O(1)的解法,不需要额外空间
有两种情况,一种是两个串联的节点都有一个共同的父节点,通过父节点就可以将这两个子节点串联起来;一种是两个串联的节点的父节点不同,对于这种情况,如果我们能将这一层的上一层串联好。那么可以通过父节点的next找到邻居,完成串联。
通过操作pre指针和tmp指针,pre指向每一层的第一个节点,tmp指向这一层的每一个节点,将所有下一层的节点都连接起来。
class Solution(object):
def connect(self, root):
"""
:type root: Node
:rtype: Node
"""
if not root:
return root
pre = root
# 循环条件是当前节点的left不为空,当只有根节点
# 或所有叶子节点都出串联完后循环就退出了
while pre.left:
tmp = pre
while tmp:
# 将tmp的左右节点都串联起来
# 注:外层循环已经判断了当前节点的left不为空
tmp.left.next = tmp.right
# 下一个不为空说明上一层已经帮我们完成串联了
if tmp.next:
tmp.right.next = tmp.next.left
# 继续右边遍历
tmp = tmp.next
# 从下一层的最左边开始遍历
pre = pre.left
return root
3)时间空间复杂度分别为O(N)、O(h)的递归解法,h是树的高度
上面两种方式利用层序遍历,属于横向的视角,而递归则像是一个深度的视角。
我们以当前节root点为起始,左右节点不断的深入下面,left节点不断往右走,right节点不断往左走,当这两个节点走到底后,整个纵深这段就完成了串联。
递归函数实现如下:
终止条件:当前节点为空时
函数内:以当前节点为起始,完成从上往下的纵深串联,再递归的调用当前节点left和right
class Solution(object):
def connect(self, root):
"""
:type root: Node
:rtype: Node
"""
def dfs(root):
# 停止条件
if not root:
return
# 完成以root为起点的整个纵深串联
left = root.left
right = root.right
while left:
left.next = right
left = left.right
right = right.left
# 递归的调用左右节点,完成同样的纵深串联
dfs(root.left)
dfs(root.right)
dfs(root)
return root
- 填充每个节点的下一个右侧节点指针 II - 非完美二叉树
class Solution:
def connect(self, root: 'Node') -> 'Node':
"""
:type root: Node
:rtype: Node
"""
queue = []
if root:
queue.append(root)
else:
return root
while queue:
size = len(queue)
# 将队列中的元素串联起来
tmp = queue[0]
for i in range(1,size):
tmp.next = queue[i]
tmp = queue[i]
# 遍历队列中的每个元素,将每个元素的左右节点也放入队列中
for _ in range(size):
tmp = queue.pop(0)
if tmp.left:
queue.append(tmp.left)
if tmp.right:
queue.append(tmp.right)
return root