
🔥小叶-duck:个人主页
❄️个人专栏:《Data-Structure-Learning》《C++入门到进阶&自我学习过程记录》
《算法题讲解指南》--优选算法
《算法题讲解指南》--递归、搜索与回溯算法
《算法题讲解指南》--动态规划算法
✨未择之路,不须回头
已择之路,纵是荆棘遍野,亦作花海遨游
目录
70.N叉树的层序遍历
题目链接:
题目描述:

题目示例:

解法:
算法思路:
层序遍历即可
仅需多加一个变量,用来记录每一层结点的个数就好了。
C++算法代码:
cpp
class Solution {
public:
vector<vector<int>> levelOrder(Node* root)
{
vector<vector<int>> ret;
queue<Node*> q;
if(root)
{
q.push(root);
}
while(q.size())
{
vector<int> tmp;
int sz = q.size();
while(sz--)
{
Node* node = q.front();
tmp.push_back(node->val);
for(auto e : node->children)
{
if(e)
{
q.push(e);
}
}
q.pop();
}
ret.push_back(tmp);
}
return ret;
}
};
算法总结及流程解析:

71.二叉树的锯齿形层序遍历
题目链接:
题目描述:

题目示例:

解法(层序遍历):
算法思路:
在正常的层序遍历过程中,我们是可以把一层的结点放在一个数组中去的。
既然我们有这个数组,在合适的层数逆序就可以得到锯齿形层序遍历的结果。
C++算法代码:
cpp
class Solution {
public:
vector<vector<int>> zigzagLevelOrder(TreeNode* root)
{
vector<vector<int>> ret;
queue<TreeNode*> q;
int flag = 0;
if(root)
{
q.push(root);
}
while(q.size())
{
int sz = q.size();
vector<int> tmp;
while(sz--)
{
TreeNode* node = q.front();
tmp.push_back(node->val);
if(node->left)
{
q.push(node->left);
}
if(node->right)
{
q.push(node->right);
}
q.pop();
}
if(flag == 0)
{
flag = 1;
}
else
{
reverse(tmp.begin(), tmp.end());
flag = 0;
}
ret.push_back(tmp);
}
return ret;
}
};
算法总结及流程解析:

72.二叉树的最大宽度
题目链接:
题目描述:

题目示例:


解法(层序遍历):
算法思路:
1.第一种思路(会超过内存限制):
既然统计每一层的最大宽度,我们优先想到的就是利用层序遍历,把当前层的结点全部存在队列里面,利用队列的长度来计算每一层的宽度,统计出最大的宽度。
但是,由于空节点也是需要计算在内的。因此,我们可以选择将空节点也存在队列里面。
这个思路是我们正常会想到的思路,但是极端境况下,最左边一条长链,最右边一条长链,我们需要存几亿个空节点,会超过最大内存限制。
2.第二种思路(利用二叉树的顺序存储 -通过根节点的下标,计算左右孩子的下标):
依旧是利用层序遍历,但是这一次队列里面不单单存结点信息,并且还存储当前结点如果在数组中存储所对应的下标(在我们学习数据结构-堆的时候,计算左右孩子的方式)。
这样我们计算每一层宽度的时候,无需考虑空节点,只需将当层结点的左右结点的下标相减再加1即可。
但是,这里有个细节问题:如果二叉树的层数非常恐怖的话,我们任何一种数据类型都不能存下下标的值。但是没有问题,因为
我们数据的存储 是一个环形的结构 ;
并且题目说明,数据的范围在int这个类型的最大值的范围之内,因此不会超出一圈;
因此,如果是求差值 的话,我们无需考虑溢出的情况。
C++算法代码:
cpp
class Solution {
public:
int widthOfBinaryTree(TreeNode* root)
{
//利用二叉树堆的底层结构数组这个特性,将结点和对应下标进行绑定
//这样就可以快速计算一层中任意两个结点之间的距离(下标之差)
queue<pair<TreeNode*, unsigned int>> q;
q.push({root, 1});
unsigned int len = 0;
while(q.size())
{
//在放入下一层数据之前将当前层的宽度进行计算并且将最大宽度进行更新
unsigned int Left = q.front().second;
unsigned int Right = q.back().second;
len = max(len, Right - Left + 1);
//让下一层数据进队列
int sz = q.size();
while(sz--)
{
if(q.front().first->left)
{
//进队前判断结点左孩子是否为空
q.push({q.front().first->left, q.front().second * 2});
}
if(q.front().first->right)
{
//进队前判断结点右孩子是否为空
q.push({q.front().first->right, q.front().second * 2 + 1});
}
q.pop();
}
}
return len;
}
};
算法总结及流程解析:



73.在每个树行中找最大值
题目链接:
题目描述:

题目示例:

解法(bfs):
算法思路:
层序遍历过程中,在执行让下一层节点入队的时候,我们是可以在循环中统计出当前层结点的最大值的。
因此,可以在 bfs 的过程中,统计出每一层结点的最大值。
cpp
class Solution {
public:
vector<int> largestValues(TreeNode* root)
{
vector<int> ret;
queue<TreeNode*> q;
if(root)
{
q.push(root);
}
while(q.size())
{
int sz = q.size();
int len = INT_MIN;
while(sz--)
{
len = max(len, q.front()->val);
if(q.front()->left)
{
q.push(q.front()->left);
}
if(q.front()->right)
{
q.push(q.front()->right);
}
q.pop();
}
ret.push_back(len);
}
return ret;
}
};
结束语
70.N叉树的层序遍历,71.二叉树的锯齿形层序遍历,72.二叉树的最大宽度,73.在每个树行中找最大值 这四道算法题就讲解完了。**N叉树层序遍历:通过队列记录每层节点数;二叉树锯齿形遍历:在层序遍历基础上适时反转数组; 二叉树最大宽度:采用节点下标差值法避免内存溢出;每层寻找最大值:通过层序遍历过程中比较节点值。**希望大家能有所收获!