- 层序遍历 10
- 226.翻转二叉树
- 101.对称二叉树 2
层序遍历
给你二叉树的根节点 root
,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)
# 递归法
# 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]]:
levels = []
self.helper(root, 0, levels) #调用辅助函数,从根节点(层级为0)开始遍历
return levels
def helper(self, node, level, levels):
if not node:
return
#如果当前层级等于层级列表的长度,说明这是一个新的层级,所以在层级列表中添加一个新的空列表
if len(levels) == level:
levels.append([])
#将当前节点的值添加到对应层级的列表中。
levels[level].append(node.val)
#递归遍历左子树,层级加1。
self.helper(node.left, level + 1, levels)
#递归遍历右子树,层级加1。
self.helper(node.right, level + 1, levels)
给你二叉树的根节点 root
,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
class Solution:
def levelOrderBottom(self, root: Optional[TreeNode]) -> List[List[int]]:
if not root:
return []
queue = collections.deque([root])
result = []
while queue:
level=[]
for _ in range(len(queue)):
cur = queue.popleft()
level.append(cur.val)
if cur.left:
queue.append(cur.left)
if cur.right:
queue.append(cur.right)
result.append(level)
return result[::-1]
二叉树输入 [3, 9, 20, null, null, 15, 7]
和代码片段的分析,让我来进一步解释这个过程:
-
初始时,队列
queue
中只有根节点3
。进入第一次循环:- 弹出节点
3
,加入3
的值到level
中。 - 发现节点
3
有左子节点9
,将9
加入队列。 - 发现节点
3
有右子节点20
,将20
加入队列。 - 此时
result
中为[3]
。
- 弹出节点
-
进入第二次循环,队列中的节点为
9
和20
:- 弹出节点
9
,加入9
的值到level
中。 - 节点
9
没有左右子节点,不做处理。 - 弹出节点
20
,加入20
的值到level
中。 - 发现节点
20
有左子节点15
,将15
加入队列。 - 发现节点
20
有右子节点7
,将7
加入队列。 - 此时
result
中为[3, 9, 20]
。
- 弹出节点
-
进入第三次循环,队列中的节点为
15
和7
:- 弹出节点
15
,加入15
的值到level
中。 - 节点
15
没有左右子节点,不做处理。 - 弹出节点
7
,加入7
的值到level
中。 - 节点
7
没有左右子节点,不做处理。 - 此时
result
中为[3, 9, 20, 15, 7]
- 弹出节点
- 翻转result
给定一个二叉树的 根节点 root
,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
class Solution {
public:
vector<int> rightSideView(TreeNode* root) {
queue<TreeNode*>que;
if(root!=NULL) que.push(root);
vector<int>result;
while(!que.empty()){
int size=que.size();
for(int i=0;i<size;i++){
TreeNode* node=que.front();
que.pop();
if(i==(size-1)) result.push_back(node->val);
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
}
return result;
}
};
给定一个非空二叉树的根节点 root
, 以数组的形式返回每一层节点的平均值。与实际答案相差 10-5
以内的答案可以被接受。
错误点:1、sum不能放在for循环里,2、result的数据类型不是int是double
class Solution {
public:
vector<double> averageOfLevels(TreeNode* root) {
queue<TreeNode*> que;
if(root!=NULL) que.push(root);
vector<double> result;
while(!que.empty()){
int size=que.size();
double sum=0;
for(int i=0;i<size;i++){
TreeNode* node=que.front();
que.pop();
sum+=node->val;
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
result.push_back(sum / size);
}
return result;
}
};
给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)。
树的序列化输入是用层序遍历,每组子节点都由 null 值分隔(参见示例)。
模板类型:记住子孩子节点的写法。
class Solution {
public:
vector<vector<int>> levelOrder(Node* root) {
queue<Node*>que;
if(root!=NULL) que.push(root);
vector<vector<int>> result;
int size=que.size();
while(!que.empty()){
int size=que.size();
vector<int> vec;
for(int i=0;i<size;i++){
Node* node=que.front();
que.pop();
vec.push_back(node->val);
for(int i=0;i<node->children.size();i++){
if(node->children[i]) que.push(node->children[i]);
}
}
result.push_back(vec);
}
return result;
}
};
给定一棵二叉树的根节点 root
,请找出该二叉树中每一层的最大值。
条件 ? 表达式1 : 表达式2
。这个运算符的工作原理如下:首先,它会计算条件表达式的结果。如果条件为真(非零),则运算符返回表达式1的值,否则返回表达式2
class Solution {
public:
vector<int> largestValues(TreeNode* root) {
queue<TreeNode*> que;
if(root!=NULL) que.push(root);
vector<int> result;
while(!que.empty()){
int size=que.size();
int maxValue=INT_MIN;
for(int i=0;i<size;i++){
TreeNode* node=que.front();
que.pop();
maxValue = node->val > maxValue ? node->val : maxValue;
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
result.push_back(maxValue);
}
return result;
}
};
给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
struct Node { int val; Node *left; Node *right; Node *next; }
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL
。
初始状态下,所有 next 指针都被设置为 NULL
。
class Solution {
public:
Node* connect(Node* root) {
queue<Node*> que;
if (root != NULL) que.push(root);
while (!que.empty()) {
int size = que.size();
// vector<int> vec;
Node* nodePre;
Node* node;
for (int i = 0; i < size; i++) {
if (i == 0) {
nodePre = que.front(); // 取出一层的头结点
que.pop();
node = nodePre;
} else {
node = que.front();
que.pop();
nodePre->next = node; // 本层前一个节点next指向本节点
nodePre = nodePre->next;
}
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
nodePre->next = NULL; // 本层最后一个节点指向NULL
}
return root;
}
};
假设我们有一个二叉树如下:
1
/ \
2 3
/ \ / \
4 5 6 7
我们运行这个函数,它会将每一层的节点通过next指针连接起来。下面是运行过程:
-
首先,将根节点1放入队列。
-
开始第一轮循环,队列中有1个节点,即1。因为这是第一个节点,所以nodePre和node都指向1,然后将1的左右子节点2和3放入队列。
-
结束第一轮循环,将1的next指针指向NULL。
-
开始第二轮循环,队列中有2个节点,即2和3。首先处理节点2,因为这是第一个节点,所以nodePre和node都指向2,然后将2的左右子节点4和5放入队列。接着处理节点3,node指向3,nodePre的next指向node,然后更新nodePre,将3的左右子节点6和7也放入队列。
-
结束第二轮循环,将3的next指针指向NULL。
-
开始第三轮循环,队列中有4个节点,即4、5、6和7。首先处理节点4,nodePre和node都指向4,然后将4的左右子节点(如果有的话)放入队列。接着处理节点5,node指向5,nodePre的next指向node,然后更新nodePre,将5的左右子节点(如果有的话)也放入队列。同样的方式处理节点6和7。
-
结束第三轮循环,将7的next指针指向NULL。
-
当队列为空时,结束整个过程。