目录
[2、类比char的存储(一个首尾相连的环,127+1!=128 = -127),虽然int可能会溢出,但是所得的差,由题目保证的32位范围内,所以结果是不会溢出的](#2、类比char的存储(一个首尾相连的环,127+1!=128 = -127),虽然int可能会溢出,但是所得的差,由题目保证的32位范围内,所以结果是不会溢出的)
解法1:直接统计nullptr的数目(这虽然是一个错误的解法,但仍有其价值)
看到最后,如果对您有所帮助,还请点赞、收藏和关注一键三连,在未来还会继续带来优秀的内容,感谢观看,我们下期再见!
一、题目解析

1、宽度定义为最左节点和最右的非空节点之间的长度
2、类比char的存储(一个首尾相连的环,127+1!=128 = -128),虽然int可能会溢出,但是所得的差,由题目保证的32位范围内,所以结果是不会溢出的
二、算法原理
解法1:直接统计nullptr的数目(这虽然是一个错误的解法,但仍有其价值)
在遇到第一个非空节点后,开始统计nullptr的数目,在遇到下一个非空节点时,返回结果
错误之处:
存在着某个测试样式,将3000个节点左右均分,所以此时最后一层的节点树大概有2^1497个这么多
但我们在学习二叉树的时候,简单模拟是通过数组实现的,可以通过给节点编号,将节点存储在数组中,所以便有了解法2
解法2:利用数组存储二叉树,给节点编号
之前的队列都是只存储节点的指针,但我们要利用编号进行宽度计算,所以queue中或者vector模拟应存储一个pair<TreeNode*,long>的类型的数据,为什么用long呢?当然是int编号溢出了
编号呢有两种,可以自行选择
1、root为0,左孩子为2*0+1,右孩子为2*0+2,其他节点也是如此
2、root为1,左孩子为2*1,右孩子为2*1+1,其他节点也是如此
宽度的保存
结合题目和 char存储的模型,我们知道了最后的结果是有效的,但是该如何保存这个宽度呢?通过unsigned int无符号整数存储这个宽度,但是为了方便得到最终的最大值,可以初始化为1(也可以处理只有根的情况)
具体过程
参考层序遍历,只不过中间有一些空节点需要处理
在对每一层遍历时,先统计队列中的元素个数,这个个数代表该层元素个数,也代表循环次数
我们first是TreeNode*,用于判断它的左右孩子是否入队(我这里选择是nullptr不入队),second是节点的编号,用于计算宽度
在层序遍历完后,取出队列对头(左端点)和队尾(右端点),计算宽度并且与上一次结果比较,如果比上次大则更新宽度,否则不更新
三、代码示例
解法2:
cpp
class Solution {
public:
int widthOfBinaryTree(TreeNode* root)
{
queue<pair<TreeNode*,int>> qti;
unsigned int ret = 1;//特殊处理只有根
if(root) qti.push({root,0});//入根
while(qti.size())
{
int num = qti.size();
pair<TreeNode*,long> tmp;//int会溢出
while(num--)//执行每层个数次
{
tmp = qti.front();
qti.pop();
if(tmp.first->left) qti.push({tmp.first->left,2*(tmp.second)+1});//不入空
if(tmp.first->right) qti.push({tmp.first->right,2*(tmp.second)+2});//通过编号计算宽度
}
if(qti.size())
ret = ret>qti.back().second-qti.front().second+1 ? ret : qti.back().second-qti.front().second+1;//取对头和队尾做计算
}
return ret;
}
};

看到最后,如果对您有所帮助,还请点赞、收藏和关注一键三连,在未来还会继续带来优秀的内容,感谢观看,我们下期再见!