第六章 二叉树part02
1.LeetCode. 翻转二叉树
1.1题目链接:226.翻转二叉树
1.2思路:该题目采用递归遍历的话可以使用前序遍历(中左右),也可以采用后序遍历(左右中),但是采用中序遍历的话容易造成出错,这里也可以采用中序遍历但不是表面上的中序遍历需要进行根据实际情况更改的中序遍历(即左中左,根据实例可以分析出来);采用层序遍历也可以实现;
1.3附加代码如下所示:
//递归法 中序遍历
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if(root==NULL)return root;
swap(root->left,root->right);//中
invertTree(root->left);//左
invertTree(root->right);//右
return root;
}
};
2.LeetCode.对称二叉树
2.1题目链接:101. 对称二叉树
2.2思路:本题遍历只能是“后序遍历”,因为我们要通过递归函数的返回值来判断两个子树的内侧节点和外侧节点是否相等。正是因为要遍历两棵树而且要比较内侧和外侧节点,所以准确的来说是一个树的遍历顺序是左右中,一个树的遍历顺序是右左中.
2.3附加代码如下所示:
//正是因为要遍历两棵树而且要比较内侧和外侧节点,所以准确的来说是一个树的遍历顺序是左右中,一个树的遍历顺序是右左中。
class Solution {
public:
bool compare(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;
// 此时就是:左右节点都不为空,且数值相同的情况
// 此时才做递归,做下一层的判断
else
{
bool outside=compare(left->left,right->right);
bool inside=compare(left->right,right->left);
bool isSame=outside&&inside;
return isSame;
}
}
bool isSymmetric(TreeNode* root) {
if(root==NULL)return true;
return compare(root->left,root->right);
}
};
3.LeetCode.二叉树层序遍历
3.1题目链接:102.二叉树的层序遍历 107.二叉树的层次遍历II 199.二叉树的右视图 637.二叉树的层平均值 429.N叉树的层序遍历 515.在每个树行中找最大值 116.填充每个节点的下一个右侧节点指针 117.填充每个节点的下一个右侧节点指针II 104.二叉树的最大深度 111.二叉树的最小深度
3.2思路:二叉树的层序遍历,就是图论中的广度优先搜索在二叉树中的应用,需要借助队列来实现(此时又发现队列的一个应用了)。
3.3附加代码如下所示:
(102.二叉树的层序遍历)
//二叉树的层序遍历递归法
class Solution {
public:
void orderlayer(TreeNode*cur,vector<vector<int>>&result,int depth)
{
if(cur==nullptr)return;
if(result.size()==depth)result.push_back(vector<int>());
result[depth].push_back(cur->val);
orderlayer(cur->left,result,depth+1);
orderlayer(cur->right,result,depth+1);
}
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>>result;
int depth=0;
orderlayer(root,result,depth);
return result;
}
};
//层序遍历法
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>>result;
queue<TreeNode*>que;
if(root==NULL)return result;
else que.push(root);
while(!que.empty())
{
int size=que.size();//记录每一层的元素个数
vector<int>vec;//用来保存每一层的元素
while(size--)
{
TreeNode*node=que.front();//记录此时的父子树
que.pop();
vec.push_back(node->val);
if(node->left)que.push(node->left);//左子树入队列
if(node->right)que.push(node->right);//右子树入队列
}
result.push_back(vec);//将每一层的元素保存在输出数组中
}
return result;
}
};
(107.二叉树的层次遍历II)
//相对于102.二叉树的层序遍历,就是最后把result数组反转一下就可以了。
class Solution {
public:
vector<vector<int>> levelOrderBottom(TreeNode* root) {
vector<vector<int>>result;
queue<TreeNode*>que;
if(root==nullptr)return result;
else que.push(root);
while(!que.empty())
{
int size=que.size();//记录每一层的元素数目
vector<int>vec;
while(size--)
{
TreeNode*node=que.front();
que.pop();
vec.push_back(node->val);
if(node->left)que.push(node->left);
if(node->right)que.push(node->right);
}
result.push_back(vec);
}
reverse(result.begin(),result.end());//反转正常自上向底的数组结果就得到自底向上的结果了
return result;
}
};
(199.二叉树的右视图)
//层序遍历的时候,判断是否遍历到单层的最后面的元素,如果是,就放进result数组中,随后返回result就可以了。
class Solution {
public:
vector<int> rightSideView(TreeNode* root) {
vector<int>result;//因为题目要求只保存有侧视图的元素所以不需要二维数组一维数组就行
queue<TreeNode*>que;
if(root==nullptr) return result;
else que.push(root);
while(!que.empty())
{
int size=que.size();
for(int i=0;i<size;i++)
{
TreeNode*node=que.front();
que.pop();
if(i==size-1) result.push_back(node->val);
if(node->left)que.push(node->left);
if(node->right)que.push(node->right);
}
}
return result;
}
};
(637.二叉树的层平均值)
class Solution {
public:
vector<double> averageOfLevels(TreeNode* root) {
vector<double>average;
queue<TreeNode*>que;
if(root==nullptr)return average;
else que.push(root);
while(!que.empty())
{
int size=que.size();
double sum=0;//这里要采用double类型,不然结果会出错,用来统计每一层的和
for(int i=0;i<size;i++)
{
TreeNode*node=que.front();
que.pop();
sum+=node->val;
if(node->left)que.push(node->left);
if(node->right)que.push(node->right);
}
average.push_back(sum/size);//将每一层的平均值放入数组中
}
return average;
}
};
(429.N叉树的层序遍历)
class Solution {
public:
vector<vector<int>> levelOrder(Node* root) {
vector<vector<int>>result;
queue<Node*>que;
if(root!=NULL)que.push(root);
while(!que.empty())
{
int size=que.size();
vector<int>vec;
for(int i=0;i<size;i++)
{
Node*node=que.front();
que.pop();
vec.push_back(node->val);
for(int j=0;j<node->children.size();j++)
{
if(node->children[j]) que.push(node->children[j]);
}
}
result.push_back(vec);
}
return result;
}
};
(515.在每个树行中找最大值)
class Solution {
public:
vector<int> largestValues(TreeNode* root) {
vector<int>result;
queue<TreeNode*>que;
if(root!=NULL) que.push(root);
while(!que.empty())
{
int size=que.size();
int max=INT_MIN;//用来存放每行也就是二叉树每层的最大值,但是max的最小值不是零,这是有符号的数值,应该是INT_MIN ,通常是 -2147483648
for(int i=0;i<size;i++)
{
TreeNode*node=que.front();
que.pop();
max=max>node->val ?max:node->val;//取每一行的最大值
if(node->left)que.push(node->left);
if(node->right)que.push(node->right);
}
result.push_back(max);
}
return result;
}
};
(116.填充每个节点的下一个右侧节点指针)
class Solution {
public:
Node* connect(Node* root) {
queue<Node*>que;
if(root!=NULL) que.push(root);
while(!que.empty())
{
int size=que.size();
Node*node;
Node*nodepre;
for(int i=0;i<size;i++)
{
if(i==0)//取出一层的第一个头节点
{
node=que.front();
que.pop();
nodepre=node;
}
else
{
node=que.front();
que.pop();
nodepre->next=node;//本层前一个结点指向本节点
nodepre=nodepre->next;
}
if(node->left)que.push(node->left);
if(node->right)que.push(node->right);
}
nodepre->next=NULL;//本层最后一个节点指向NULL
}
return root;
}
};
(117.填充每个节点的下一个右侧节点指针II)
class Solution {
public:
Node* connect(Node* root) {
queue<Node*>que;
if(root!=NULL) que.push(root);
while(!que.empty())
{
int size=que.size();
Node*node;
Node*nodepre;
for(int i=0;i<size;i++)
{
if(i==0)//取出一层的第一个头节点
{
node=que.front();
que.pop();
nodepre=node;
}
else
{
node=que.front();
que.pop();
nodepre->next=node;//本层前一个结点指向本节点
nodepre=nodepre->next;
}
if(node->left)que.push(node->left);
if(node->right)que.push(node->right);
}
nodepre->next=NULL;//本层最后一个节点指向NULL
}
return root;
}
};
(104.二叉树的最大深度)
//本题求二叉树的深度从另一方面来说就是求层序遍历的深度,所以采用层序遍历就能直接得到结果
class Solution {
public:
int maxDepth(TreeNode* root) {
queue<TreeNode*>que;
if(root!=NULL)que.push(root);
int count=0;
while(!que.empty())
{
int size=que.size();
for(int i=0;i<size;i++)
{
TreeNode*node=que.front();
que.pop();
if(node->left)que.push(node->left);
if(node->right)que.push(node->right);
}
count++;
}
return count;
}
};
(111.二叉树的最小深度)
//需要注意的是,只有当左右孩子都为空的时候,才说明遍历的最低点了。如果其中一个孩子为空则不是最低点
class Solution {
public:
int minDepth(TreeNode* root) {
queue<TreeNode*>que;
if(root!=NULL)que.push(root);
int count=0;
while(!que.empty())
{
int size=que.size();
count++;//因为根节点已经加入了表明深度为1了;这是计算多少个节点数目了
for(int i=0;i<size;i++)
{
TreeNode*node=que.front();
que.pop();
if(node->left)que.push(node->left);
if(node->right)que.push(node->right);
if(node->left==NULL&&node->right==NULL)//也就是首先碰到的左右子树均为空指针的就是最近子树
{
return count;
}
}
}
return count;
}
};