LeetCode-Binary Tree Zigzag Level Order Traversal一种算法
题目链接:https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/description/
Given a binary tree, return the zigzag level order traversal of its nodes’ values. (ie, from left to right, then right to left for the next level and alternate between).
For example:
Given binary tree [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
return its zigzag level order traversal as:
[
[3],
[20,9],
[15,7]
]
根据题目,要求我们横向遍历一个二叉树,奇数层从左到右,偶数层从右到左,并将每一层的节点用保存下来,最终组成一个二维数组。
本次解题思路比较明确,可以用广度优先搜索(BFS)从根节点开始一层层遍历(不过实际上LeetCode上给出的最佳算法采用的深度优先搜索算法(DFS))。难点在于每遍历一层就需要更改遍历的方向顺序,最初本人是打算用一个记录数组遍历层数的整型变量Level来处理,但是判断遍历层数过程中遇到了一点麻烦,考虑再三决定采用双vector容器来处理交错问题,一个容器保存奇数层的遍历结果,一个容器保存偶数层的遍历结果。
具体算法如下。
- 将root放入从左到右容器
- 当两容器不为空(即未遍历完所有节点)时,按要求的方向循环遍历节点,并将子节点反向存入另一个容器。
- 当一个容器遍历完时,即完成一层的遍历,保存结果后开始遍历下一层,即对另一个容器保存的节点进行遍历。
- 以此交替循环知道两容器为空为止。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
vector<vector<int>> all;
if (root == NULL) return all; //当根节点为空,返回结果
BFS(root, all);
return all;
}
void BFS(TreeNode* root, vector<vector<int>>& all) {
vector<TreeNode*> vLeft; //从左到右容器
vector<TreeNode*> vRight; //从右到左容器
vector<int> row; //存放每一层遍历的结果
vLeft.push_back(root); //将根节点放入左容器
TreeNode* node;
while(!vLeft.empty() || !vRight.empty()) { //大循环,用以循环遍历每一层
while (!vLeft.empty()) { //小循环,遍历奇数层
node = vLeft.back();
row.push_back(node->val); //保存节点值
vLeft.pop_back(); //删除已遍历的节点
//由于容器中的节点操作是由后往前进行
//所以是由左往右将子节点放入右容器中
if (node->left != NULL) {
vRight.push_back(node->left);
}
if (node->right != NULL) {
vRight.push_back(node->right);
}
}
if (!row.empty()) {
all.push_back(row); //将当前整个遍历层的结果数组保存下来
}
row.clear(); //清空用以临时记录节点值的数组
//原理同上
while (!vRight.empty()) {
node = vRight.back();
row.push_back(node->val);
vRight.pop_back();
if (node->right != NULL) {
vLeft.push_back(node->right);
}
if (node->left != NULL) {
vLeft.push_back(node->left);
}
}
if (!row.empty()) {
all.push_back(row);
}
row.clear();
}
}
};
本次算法并不是最优解,但是确实采用BFS进行的,比较符合题目本身在LeetCode上的分类(LeetCode上把这一题划分到BFS算法中)。在这里顺便提一下本人打算使用Level判断遍历方向时遇到的问题,那就是当只使用一个vector容器时,需要把子节点与父节点保存在一个容器中,这样会造成操作容器时的混乱。
不过实际上也不是不能实现就是了,只是因为觉得麻烦而已。