(算法)⼆叉树的最⼤宽度————<队列—深搜>

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;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

课堂随笔

感谢支持~~~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值