二叉树的层序遍历要求从上到下,从左到右遍历整颗树;
这里提供两种解法,都是使用单队列。
二叉树的定义如下:
// C++
//Definition for a binary tree node.
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
解法一:
使用 nullptr 分割不同层的节点。具体做法是先入队一个空指针,再入队头节点,每次检测到 nullptr 就意味着到了新的一层,这时抛出这个 nullptr, 然后在队尾入队一个 nullptr;否则就访问队列头元素并将队列头元素的所有孩子入队。代码如下:
// C++
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> vecOfAns;
if (!root) return vecOfAns; // 树为空,返回空容器
queue<TreeNode*> queueOfNode;
TreeNode* p = nullptr;
int level = -1; // 层号
queueOfNode.push(nullptr); // 入队一个空指针
queueOfNode.push(root); // 入队头节点
while (queueOfNode.size() != 1) { // 遍历完树后队列中最后会有一个空指针 nullptr
p = queueOfNode.front();
if (p == nullptr) {
queueOfNode.push(nullptr); // 使用空指针分割不同的层
++level; // 层号加1
vecOfAns.push_back({}); // 新建一个空vector容器
}
else {
vecOfAns[level].push_back(p->val); // 访问节点
if (p->left) // 入队左右孩子
queueOfNode.push(p->left);
if (p->right)
queueOfNode.push(p->right);
}
queueOfNode.pop();
}
return vecOfAns;
}
};
时间复杂度:O(n) : 每个节点访问一遍
解法二:
解法二是每次统计队列中的元素个数,这个元素个数也是本层或者说下层节点的数量,然后在一个 for 循环中访问这些节点,每次 for 循环访问本层所有节点。代码如下:
// C++
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
queue<TreeNode*> queueOfNode;
vector<vector<int>> vecOfAns;
if(root == nullptr) return vecOfAns;
queueOfNode.push(root);
while( !queueOfNode.empty() ) { // 队列非空
int size = queueOfNode.size(); // 树本层的节点数
vector<int> tmp; // 存储本层的遍历序列
for(int i =0; i < size; ++i) { // 访问本层的所有节点
TreeNode* ptrTmp = queueOfNode.front(); // 取出队列头元素
queueOfNode.pop(); // 抛出队列头元素
tmp.push_back(ptrTmp->val); // 访问节点
if(ptrTmp->left != nullptr) // 入队左右孩子
queueOfNode.push(ptrTmp->left);
if(ptrTmp->right != nullptr)
queueOfNode.push(ptrTmp->right);
}
vecOfAns.push_back(tmp); // 本层遍历序列入 vector
}
return vecOfAns;
}
};
时间复杂度:O(n) : 不得不说,在力扣上算法二比算法一快,同时说明,算法二参考自力扣