面试经典算法18 - 二叉树的层序遍历
LeetCode.102
公众号:阿Q技术站
问题描述
给你二叉树的根节点 root
,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
示例 1:
输入:root = [3,9,20,null,null,15,7]
输出:[[3],[9,20],[15,7]]
示例 2:
输入:root = [1]
输出:[[1]]
示例 3:
输入:root = []
输出:[]
提示:
- 树中节点数目在范围
[0, 2000]
内 -1000 <= Node.val <= 1000
思路
递归
- 定义一个辅助函数
levelOrderHelper
,用来递归遍历二叉树的每一层,并将节点值按层级存储在result
中。 - 辅助函数的参数包括当前节点
root
、当前层级level
和存储结果的二维数组result
。 - 如果当前节点为空,则直接返回。
- 如果当前层级大于等于
result
的大小,说明需要添加新的一层,因为层序遍历是逐层遍历的。 - 将当前节点的值加入到
result
的对应层级中。 - 递归遍历当前节点的左子树,层级加一。
- 递归遍历当前节点的右子树,层级加一。
- 主函数
levelOrder
中调用辅助函数levelOrderHelper
开始遍历整棵树。 - 最后返回存储结果的二维数组
result
。
非递归
- 创建一个队列
queue
和一个存储结果的二维数组result
。 - 将根节点入队。
- 循环直到队列为空:
- 从队列中取出一个节点,将其值存储到当前层级的结果数组中。
- 如果节点有左子节点,则将左子节点入队。
- 如果节点有右子节点,则将右子节点入队。
- 将当前层级的结果数组加入到最终的结果中。
- 继续循环直到队列为空,完成整个二叉树的层序遍历。
图解
- 创建一个队列
queue
和一个存储结果的二维数组result
,将根节点入队。
- 队列不为空时,新建一个空数组level,用于存储当前层级节点值,然后进行循环打印,循环次数为当前层的节点数,也就是队列的长度。
- 将队头元素弹出,存入当前层级的数组中。
- 接着将当前节点的左右节点依次入队(如果有),然后将当前层级的节点值数组加入结果中。
- 继续第3步。
- 继续第4步。
- 继续第3步。
- 继续第4步。
此时,队列为空,退出循环,返回结果集。
参考代码
C++
递归
#include <iostream>
#include <vector>using namespace std;// 二叉树节点的定义
struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};// 辅助函数,递归实现层序遍历
void levelOrderHelper(TreeNode* root, int level, vector<vector<int>>& result) {if (!root) return;if (level >= result.size()) {result.push_back({});}result[level].push_back(root->val);levelOrderHelper(root->left, level + 1, result);levelOrderHelper(root->right, level + 1, result);
}// 主函数,返回二叉树的层序遍历结果
vector<vector<int>> levelOrder(TreeNode* root) {vector<vector<int>> result;levelOrderHelper(root, 0, result);return result;
}// 创建二叉树
TreeNode* createTree(vector<int>& nodes, int index) {if (index >= nodes.size() || nodes[index] == -1) {return nullptr; // 如果节点为空,则返回nullptr}TreeNode* root = new TreeNode(nodes[index]); // 创建当前节点root->left = createTree(nodes, 2 * index + 1); // 创建左子树root->right = createTree(nodes, 2 * index + 2); // 创建右子树return root; // 返回当前节点
}// 销毁二叉树
void destroyTree(TreeNode* root) {if (!root) return; // 如果根节点为空,直接返回destroyTree(root->left); // 递归销毁左子树destroyTree(root->right); // 递归销毁右子树delete root; // 删除当前节点
}int main() {// 输入数据,示例二叉树为 {3,9,20,#,#,15,7}vector<int> nodes = {3, 9, 20, -1, -1, 15, 7};TreeNode* root = createTree(nodes, 0); // 创建二叉树// 调用层序遍历函数vector<vector<int>> result = levelOrder(root);// 输出遍历结果for (vector<int> level : result) {for (int val : level) {cout << val << " ";}cout << endl;}// 销毁二叉树destroyTree(root);return 0;
}
非递归
#include <iostream>
#include <vector>
#include <queue>using namespace std;// 二叉树节点的定义
struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};vector<vector<int>> levelOrder(TreeNode* root) {vector<vector<int>> result; // 存储结果的二维数组if (!root) return result; // 如果根节点为空,直接返回空结果数组queue<TreeNode*> q; // 辅助队列,用于层序遍历q.push(root); // 将根节点入队while (!q.empty()) {int size = q.size(); // 当前层级的节点数vector<int> level; // 存储当前层级节点值的数组for (int i = 0; i < size; i++) {TreeNode* node = q.front(); // 获取队头节点q.pop(); // 弹出队头节点level.push_back(node->val); // 将节点值加入当前层级的数组中if (node->left) q.push(node->left); // 将左子节点入队if (node->right) q.push(node->right); // 将右子节点入队}result.push_back(level); // 将当前层级的节点值数组加入结果中}return result; // 返回层序遍历的结果数组
}// 创建二叉树
TreeNode* createTree(vector<int>& nodes, int index) {if (index >= nodes.size() || nodes[index] == -1) {return nullptr; // 如果节点为空,则返回nullptr}TreeNode* root = new TreeNode(nodes[index]); // 创建当前节点root->left = createTree(nodes, 2 * index + 1); // 创建左子树root->right = createTree(nodes, 2 * index + 2); // 创建右子树return root; // 返回当前节点
}// 销毁二叉树
void destroyTree(TreeNode* root) {if (!root) return; // 如果根节点为空,直接返回destroyTree(root->left); // 递归销毁左子树destroyTree(root->right); // 递归销毁右子树delete root; // 删除当前节点
}int main() {vector<int> nodes = {3, 9, 20, -1, -1, 15, 7}; // 二叉树的层序遍历序列TreeNode* root = createTree(nodes, 0); // 创建二叉树vector<vector<int>> result = levelOrder(root); // 进行层序遍历for (auto& level : result) { // 输出遍历结果for (int val : level) {cout << val << " ";}cout << endl;}destroyTree(root); // 销毁二叉树return 0;
}
Java
import java.util.*;// 二叉树节点的定义
class TreeNode {int val;TreeNode left;TreeNode right;TreeNode(int x) { val = x; }
}public class Main {public List<List<Integer>> levelOrder(TreeNode root) {List<List<Integer>> result = new ArrayList<>(); // 存储结果的二维数组if (root == null) return result; // 如果根节点为空,直接返回空结果数组Queue<TreeNode> queue = new LinkedList<>(); // 辅助队列,用于层序遍历queue.offer(root); // 将根节点入队while (!queue.isEmpty()) {int size = queue.size(); // 当前层级的节点数List<Integer> level = new ArrayList<>(); // 存储当前层级节点值的数组for (int i = 0; i < size; i++) {TreeNode node = queue.poll(); // 获取队头节点level.add(node.val); // 将节点值加入当前层级的数组中if (node.left != null) queue.offer(node.left); // 将左子节点入队if (node.right != null) queue.offer(node.right); // 将右子节点入队}result.add(level); // 将当前层级的节点值数组加入结果中}return result; // 返回层序遍历的结果数组}// 创建二叉树public TreeNode createTree(Integer[] nodes, int index) {if (index >= nodes.length || nodes[index] == null) {return null; // 如果节点为空,则返回null}TreeNode root = new TreeNode(nodes[index]); // 创建当前节点root.left = createTree(nodes, 2 * index + 1); // 创建左子树root.right = createTree(nodes, 2 * index + 2); // 创建右子树return root; // 返回当前节点}// 销毁二叉树public void destroyTree(TreeNode root) {if (root == null) return; // 如果根节点为空,直接返回destroyTree(root.left); // 递归销毁左子树destroyTree(root.right); // 递归销毁右子树root = null; // 将当前节点置为null}public static void main(String[] args) {Integer[] nodes = {3, 9, 20, null, null, 15, 7}; // 二叉树的层序遍历序列Main main = new Main();TreeNode root = main.createTree(nodes, 0); // 创建二叉树List<List<Integer>> result = main.levelOrder(root); // 进行层序遍历for (List<Integer> level : result) { // 输出遍历结果for (int val : level) {System.out.print(val + " ");}System.out.println();}main.destroyTree(root); // 销毁二叉树}
}
Python
from typing import List
from collections import deque# 二叉树节点的定义
class TreeNode:def __init__(self, val=0, left=None, right=None):self.val = valself.left = leftself.right = rightdef levelOrder(root: TreeNode) -> List[List[int]]:result = [] # 存储结果的二维数组if not root:return result # 如果根节点为空,直接返回空结果数组queue = deque([root]) # 辅助队列,用于层序遍历while queue:level_size = len(queue) # 当前层级的节点数level = [] # 存储当前层级节点值的数组for _ in range(level_size):node = queue.popleft() # 获取队头节点level.append(node.val) # 将节点值加入当前层级的数组中if node.left:queue.append(node.left) # 将左子节点入队if node.right:queue.append(node.right) # 将右子节点入队result.append(level) # 将当前层级的节点值数组加入结果中return result # 返回层序遍历的结果数组# 创建二叉树
def createTree(nodes: List[int], index: int) -> TreeNode:if index >= len(nodes) or nodes[index] is None:return None # 如果节点为空,则返回Noneroot = TreeNode(nodes[index]) # 创建当前节点root.left = createTree(nodes, 2 * index + 1) # 创建左子树root.right = createTree(nodes, 2 * index + 2) # 创建右子树return root # 返回当前节点# 销毁二叉树
def destroyTree(root: TreeNode) -> None:if not root:return # 如果根节点为空,直接返回destroyTree(root.left) # 递归销毁左子树destroyTree(root.right) # 递归销毁右子树root = None # 将当前节点置为None# 测试代码
nodes = [3, 9, 20, None, None, 15, 7] # 二叉树的层序遍历序列
root = createTree(nodes, 0) # 创建二叉树
result = levelOrder(root) # 进行层序遍历
for level in result: # 输出遍历结果print(level)destroyTree(root) # 销毁二叉树