leetcode刷题之层序遍历
剑指 Offer 32 - I. 从上到下打印二叉树 I
个人感觉这达不到中等难度,应该是简单题,就一个层序遍历。
从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。
例如:
给定二叉树: [3,9,20,null,null,15,7]
,
返回:[3,9,20,15,7]
思路:
1.创建一维数组用于接收结果,创建队列用于接收每个节点的子节点
2.对队列进行遍历,在队列不为空时,不断地遍历节点是否有子节点,每一次遍历节点都要将节点取出来防止重复,如果节点有子节点按左到右的顺序存入队列中,不断遍历直到队列为空,整棵树遍历完成。
/**
* 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<int> levelOrder(TreeNode* root) {
//定义数组用于接收遍历的结果
vector<int> res;
//判断二叉树是否为空,当它为空时,返回res,res为NULL
if(root==NULL) return res;
//创建队列,实现层序的效果,用于接收每个根节点的子节点(左右节点)
queue<TreeNode*> q;
//将数的根节点存入队列中,这是第一层
q.push(root);
//当队列不为空时,循环将一直运行
while(q.size())
{
//创建节点,用于遍历树
TreeNode* node = q.front();
//将根节点的值存入接收结果数组中
res.push_back(node->val);
//该节点遍历完成,将该节点取出
q.pop();
//判断二叉树的节点是否有左右子树,如果有将节点存入队列中,这些节点属于下一层
if(node->left) q.push(node->left);
if(node->right) q.push(node->right);
}
//返回结果
return res;
}
};
剑指 Offer 32 - II. 从上到下打印二叉树 II
从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
返回其层次遍历的结果:
思路:
1.定义二维数组用于接收遍历结果,定义队列用于逐层遍历
2.在队列不为空的情况下,定义一维数组用于存放当前层的遍历数据,定义size获取当前队列长度,利用循环遍历每一层的数据,将遍历的数据存入一维数组,将遍历的每个节点的子节点的值存入队列中,在当前层的节点的值遍历完成后将已经存入当前层数据的一维数组存入二维数组中,依次逐层遍历并将每一层的节点值数组存入二维数组中。
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
//接收结果
vector<vector<int>> res;
//队列为空的情况下,返回空数组
if(root==NULL) return res;
queue<TreeNode*> q;
q.push(root);
while(q.size())
{
int size = q.size();
//定义一维数组用于存放遍历的节点值
vector<int> t;
for(int i = 0;i < size;i++)
{
TreeNode* node = q.front();
q.pop();
t.push_back(node->val);
//判断节点是否有子节点,有子节点就存入队列
if(node->left) q.push(node->left);
if(node->right) q.push(node->right);
}
//将遍历过的节点数组存入二维数组
res.push_back(t);
}
return res;
}
};
剑指 Offer 32 - III. 从上到下打印二叉树 III
请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。
思路:
与上面的一题类似,添加一个标志位Flag,用于辨别奇偶,当是奇数层时从左到右的顺序打印,当是偶数层时从右向左顺序打印。利用循环的次数不断给Flag取反,由false->true和true->false。
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
//接收结果
vector<vector<int>> res;
//队列为空的情况下,返回空数组
if(root==NULL) return res;
queue<TreeNode*> q;
q.push(root);
//定义标志位位false
bool Flag = false;
while(q.size())
{
int size = q.size();
vector<int> t;
for(int i = 0;i < size;i++)
{
TreeNode* node = q.front();
q.pop();
t.push_back(node->val);
if(node->left) q.push(node->left);
if(node->right) q.push(node->right);
}
//给标志位取反,当Flag为true时,将遍历结果倒置,当Flag为false时,正常存入结果。
Flag = !Flag;
if(!Flag)
{
res.push_back(vector<int>(t.rbegin(),t.rend()));
}
else
{
res.push_back(t);
}
}
return res;
}
};
总结:
顾名思义,对于树型结构,层序遍历就是按层从上到下,每层按一定顺序对树的节点进行遍历。我们通过如图所示的二叉树进行说明:对于左边的二叉树,按层划分后可得到右边的分层结构。
如果按照每层从左到右的遍历逻辑,这棵二叉树的层序遍历序列就是 [ 3,9,20,15,7 ] 。通过代码如何实现呢?一般地,我们利用队列queue 作为容器,按照如下逻辑进行遍历:
//定义数组用于接收遍历的结果
vector<int> res;
//判断二叉树是否为空,当它为空时,返回res,res为NULL
if(root==NULL) return res;
//创建队列,实现层序的效果,用于接收每个根节点的子节点(左右节点)
queue<TreeNode*> q;
//将数的根节点存入队列中,这是第一层
q.push(root);
//当队列不为空时,循环将一直运行
while(q.size())
{
//创建节点,用于遍历树
TreeNode* node = q.front();
//将根节点的值存入接收结果数组中
res.push_back(node->val);
//该节点遍历完成,将该节点取出
q.pop();
//判断二叉树的节点是否有左右子树,如果有将节点存入队列中,这些节点属于下一层
if(node->left) q.push(node->left);
if(node->right) q.push(node->right);
}
为了防止有空节点,加入if判断,当子节点非空才存入队列,为空的节点放弃。