1. 题⽬链接:662.⼆叉树最⼤宽度
2. 题⽬描述:
3. 解法(层序遍历):
算法思路:
1. 第⼀种思路(会超过内存限制):
既然统计每⼀层的最⼤宽度,我们优先想到的就是利⽤层序遍历,把当前层的结点全部存在队列⾥ ⾯,利⽤队列的⻓度来计算每⼀层的宽度,统计出最⼤的宽度。
但是,由于空节点也是需要计算在内的。因此,我们可以选择将空节点也存在队列⾥⾯。
这个思路是我们正常会想到的思路,但是极端境况下,最左边⼀条⻓链,最右边⼀条⻓链,我们需要 存⼏亿个空节点,会超过最⼤内存限制。
2. 第⼆种思路(利⽤⼆叉树的顺序存储-通过根节点的下标,计算左右孩⼦的下标):
依旧是利⽤层序遍历,但是这⼀次队列⾥⾯不单单存结点信息,并且还存储当前结点如果在数组中存 储所对应的下标(在我们学习数据结构-堆的时候,计算左右孩⼦的⽅式)。
这样我们计算每⼀层宽度的时候,⽆需考虑空节点,只需将当层结点的左右结点的下标相减再加1 即 可。
但是,这⾥有个细节问题:如果⼆叉树的层数⾮常恐怖的话,我们任何⼀种数据类型都不能存下下标 的值。但是没有问题,因为
• 我们数据的存储是⼀个环形的结构;
• 并且题⽬说明,数据的范围在int 这个类型的最⼤值的范围之内,因此不会超出⼀圈;
• 因此,如果是求差值的话,我们⽆需考虑溢出的情况。
C++算法代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution
{
public:
int widthOfBinaryTree(TreeNode* root)
{
vector<pair<TreeNode*,unsigned int>> q; //数组模拟队列
unsigned int max_num=0; //最大宽度
q.push_back({root,1});
while(q.size())
{
//计算宽度
auto& [x1,y1]=q[0];
auto& [x2,y2]=q.back();
max_num=max(max_num,y2-y1+1);
//入队+更新队列
vector<pair<TreeNode*,unsigned int>> temp;
for(auto& [x,y]:q)
{
if(x->left)
{
temp.push_back({x->left,2*y});
}
if(x->right)
{
temp.push_back({x->right,2*y+1});
}
}
q=temp;
}
return max_num;
}
};
Java算法代码:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution
{
public int widthOfBinaryTree(TreeNode root)
{
List<Pair<TreeNode, Integer>> q = new ArrayList<>(); // ⽤数组模拟队列
q.add(new Pair<TreeNode, Integer>(root, 1));
int ret = 0; // 记录最终结果
while (!q.isEmpty())
{
// 先更新⼀下这⼀层的宽度
Pair<TreeNode, Integer> t1 = q.get(0);
Pair<TreeNode, Integer> t2 = q.get(q.size() - 1);
ret = Math.max(ret, t2.getValue() - t1.getValue() + 1);
// 让下⼀层进队
List<Pair<TreeNode, Integer>> tmp = new ArrayList<>();
for (Pair<TreeNode, Integer> t : q)
{
TreeNode node = t.getKey();
int index = t.getValue();
if (node.left != null)
{
tmp.add(new Pair<TreeNode, Integer>(node.left, index * 2));
}
if (node.right != null)
{
tmp.add(new Pair<TreeNode, Integer>(node.right, index * 2
+ 1));
}
}
q = tmp;
}
return ret;
}
}