层序遍历:一共有十个题目
层序遍历其实并不难。这个题目的难点在于题目要求返回的是一个二维数组。你需要将每层的元素放在一个数组中然后加入到二维数组中。
那就意味着,你不能直接一次性遍历下去,而是需要一个size来记录每一层节点的数量。
二叉树的层序遍历可以使用队列来实现。如果题目不要求输出二维数组的话,可以直接通过将根节点先加入队列,然后写一个while循环,先将队头元素出队,然后记录队头元素,然后将队头元素的左孩子和右孩子都加入队列中,直到队列中没有元素,停止循环。
这题需要记录每一层的孩子个数,所以我们不能一个while循环用到底,而是需要用一个整数size来记录每层节点的个数,然后再while循环中再写一个while循环,循环次数为该层节点的个数。
代码如下:
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
queue<TreeNode*> que;
vector<vector<int>> result;
if(root==NULL) return result;
que.push(root);
TreeNode*cur = root;
while(!que.empty())
{
vector<int> vec;
int size = que.size();
while(size--)
{
cur = que.front();
que.pop();
vec.push_back(cur->val);
if(cur->left)
{
que.push(cur->left);
}
if(cur->right) que.push(cur->right);
}
result.push_back(vec);
}
return result;
}
};
这个题目看上去非常复杂,第一时间看到,可能会想半天该怎么把cur指针指向最后一层。
但是仔细看看题目,其实不难想到可以先用上一题的层序遍历求出结果,然后在返回结果的时候将结果数组反转就行了。
代码如下:
class Solution {
public:
vector<vector<int>> levelOrderBottom(TreeNode* root) {
vector<vector<int>> result;
queue<TreeNode*> que;
if(root==NULL) return result;
que.push(root);
TreeNode*cur = root;
while(!que.empty())
{
vector<int> vec;
int size = que.size();
while(size--)
{
cur = que.front();
que.pop();
vec.push_back(cur->val);
if(cur->left) que.push(cur->left);
if(cur->right) que.push(cur->right);
}
result.push_back(vec);
}
reverse(result.begin(),result.end());
return result;
}
};
这题也可以用层序遍历的方法。普通层序遍历是将每一层的所有元素都放入数组,这题可以只把每一层的最右边元素放入数组。还是用一个size记录每层的节点个数。但是只有在size==0的时候,才把节点的元素值加入数组。这样就做到了将节点的最后一个元素放入数组中。
代码如下:
class Solution {
public:
vector<int> rightSideView(TreeNode* root) {
vector<int> result;
queue<TreeNode*>que;
if(root==NULL)return result;
que.push(root);
TreeNode*cur = root;
while(!que.empty())
{
int size = que.size();
//for(int i =0;i<size;i++)
while(size--)
{
cur = que.front();
que.pop();
if(size==0) result.push_back(cur->val);
if(cur->left) que.push(cur->left);
if(cur->right) que.push(cur->right);
}
}
return result;
}
};
这题还是比较简单。还是用层序遍历,需要用一个size来记录每层节点个数。然后可以定义一个数,来记录每层节点元素值的和,然后除原先的size就能得到平均值。
代码如下:
class Solution {
public:
vector<double> averageOfLevels(TreeNode* root) {
vector<double> result;
queue<TreeNode*>que;
if(root==NULL) return result;
TreeNode*cur = root;
que.push(root);
while(!que.empty())
{
int size = que.size();
int size1 = size;
double nums = 0;
while(size--)
{
cur = que.front();
que.pop();
nums += cur->val;
if(cur->left) que.push(cur->left);
if(cur->right) que.push(cur->right);
}
double ave = nums/size1;
result.push_back(ave);
}
return result;
}
};
要做这个题,我们得先了解N叉树得定义。毕竟二叉树得节点中只有两个指针,而N叉树中是通过一个数组来存放孩子节点的。知道这个之后,其实进行层序遍历的做法就和二叉树差不多了,还是用size来记录每层节点的个数。
需要注意的是,要将N叉树的所有孩子遍历也需要用来一个循环,来从左到右遍历其孩子。
代码如下:
class Solution {
public:
vector<vector<int>> levelOrder(Node* root) {
vector<vector<int>> result;
queue<Node*> que;
if(root==NULL) return result;
Node*cur = root;
que.push(root);
while(!que.empty())
{
vector<int> vec;
int size = que.size();
while(size--)
{
cur = que.front();
que.pop();
vec.push_back(cur->val);
for(int i =0;i<cur->children.size();i++)
{
if(cur->children[i]) que.push(cur->children[i]);
}
}
result.push_back(vec);
}
return result;
}
};
这题还是很简单,还是层序遍历。我们可以定义一个数max,令他为最小值也就是max=INT32_MIN,用一个三目运算符max = max>cur->val?max:cur->val;来记录每层中的最大值。
代码如下:
class Solution {
public:
vector<int> largestValues(TreeNode* root) {
vector<int> result;
queue<TreeNode*>que;
if(root==NULL) return result;
TreeNode*cur = root;
que.push(root);
while(!que.empty())
{
int size = que.size();
int max = INT32_MIN;
while(size--)
{
cur = que.front();
que.pop();
max = max>cur->val?max:cur->val;
if(cur->left) que.push(cur->left);
if(cur->right) que.push(cur->right);
}
result.push_back(max);
}
return result;
}
};
这题还是挺麻烦的。前面的题目内存循环我们用的几乎都是while循环,但是while循环很难找到第一个节点。而且前面的题目基本上只用了一个位置指针,这题我们需要两个位置指针。所以这题,我们内存循环使用for循环,先将每一层的第一个节点取出来。两个位置指针最开始都指向每层的第一个节点。然后其中位置指针cur1接收从队列中弹出来的节点,也就是除第一个节点外的后续节点。将第一个节点的位置指向,后续节点。然后在将第一个节点位置换到后续节点的位置。
也算是一种双指针法吧。
代码如下:
class Solution {
public:
Node* connect(Node* root) {
if(root==NULL) return root;
queue<Node*>que;
que.push(root);
while(!que.empty())
{
Node*cur1;
Node*cur2;
int size = que.size();
for(int i =0;i<size;i++)
{
if(i==0)
{
cur1 = que.front();
que.pop();
cur2 = cur1;
}
else
{
cur1 = que.front();
que.pop();
cur2 ->next = cur1;
cur2 = cur1;
}
if(cur1->left) que.push(cur1->left);
if(cur1->right) que.push(cur1->right);
}
}
return root;
}
};
和上一题一模一样的思路和代码。
这题可以用层序遍历的方法,只需要在循环前定义一个深度deep,每遍历一层将deep+1.
代码如下:
class Solution {
public:
int maxDepth(TreeNode* root) {
if(root==NULL) return 0;
queue<TreeNode*>que;
que.push(root);
TreeNode*cur = root;
int deep = 0;
while(!que.empty())
{
int size = que.size();
while(size--)
{
cur = que.front();
que.pop();
if(cur->left) que.push(cur->left);
if(cur->right) que.push(cur->right);
}
deep = deep +=1;
}
return deep;
}
};
这题其实也不难,还是用层序遍历的方法,加一个条件,就是位置指针指向的节点左右孩子都为空则是最小深度。
class Solution {
public:
int minDepth(TreeNode* root) {
if(root==NULL ) return 0;
queue<TreeNode*> que;
que.push(root);
TreeNode*cur = root;
int deep = 0;
while(!que.empty())
{
deep = deep+1;
int size = que.size();
while(size--)
{
cur = que.front();
que.pop();
if(cur->left) que.push(cur->left);
if(cur->right) que.push(cur->right);
if(!cur->left&&!cur->right) return deep;
}
}
return deep;
}
};
这题很简单,直接用递归,递归结束条件为根节点指向空。递归内容为建立一个临时节点,用来存放左孩子,然后将左孩子和右孩子交换。将左孩子和右孩子重新执行一遍代码。
代码如下:
class Solution {
public:
void digui(TreeNode*root)
{
if(root==NULL) return;
TreeNode*temp = root->left;
root->left = root->right;
root->right = temp;
digui(root->left);
digui(root->right);
}
TreeNode* invertTree(TreeNode* root) {
digui(root);
return root;
}
};
这个题,我第一时间的想法是,将左子树进行翻转,然后判断左右子树是否相等,如果相等则返回true,如果不相等则返回false。后来写了一下代码发现不行。
看了一下卡哥的讲解。总结了一下本题的解法:
可以使用递归的方式,比较左右子树的位置和值。使用后序遍历的方式,也就是从最后一层节点开始比较,然后慢慢往上比较。必须左右子树的位置为镜像并且值相等都满足才返回true。
具体讲解还是看代码随想录,我讲不太清楚。
代码如下:
class Solution {
public:
bool digui(TreeNode*left,TreeNode*right)
{
if(left!=NULL&&right==NULL) return false;
else if(left==NULL&&right!=NULL) return false;
else if(left==NULL&&right==NULL) return true;
else if(left->val!=right->val) return false;
bool waice = digui(left->left,right->right);
bool neice = digui(left->right,right->left);
bool result = waice&&neice;
return result;
}
bool isSymmetric(TreeNode* root) {
if(root==NULL) return true;
return digui(root->left,root->right);
}
};