Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LeetCode] 662. Maximum Width of Binary Tree #662

Open
grandyang opened this issue May 30, 2019 · 0 comments
Open

[LeetCode] 662. Maximum Width of Binary Tree #662

grandyang opened this issue May 30, 2019 · 0 comments

Comments

@grandyang
Copy link
Owner

grandyang commented May 30, 2019

 

Given a binary tree, write a function to get the maximum width of the given tree. The width of a tree is the maximum width among all levels. The binary tree has the same structure as a full binary tree, but some nodes are null.

The width of one level is defined as the length between the end-nodes (the leftmost and right most non-null nodes in the level, where the null nodes between the end-nodes are also counted into the length calculation.

Example 1:

Input: 

           1
         /   \
        3     2
       / \     \  
      5   3     9 

Output: 4
Explanation: The maximum width existing in the third level with the length 4 (5,3,null,9).

Example 2:

Input: 

          1
         /  
        3    
       / \       
      5   3     

Output: 2
Explanation: The maximum width existing in the third level with the length 2 (5,3).

Example 3:

Input: 

          1
         / \
        3   2 
       /        
      5      

Output: 2
Explanation: The maximum width existing in the second level with the length 2 (3,2).

Example 4:

Input: 

          1
         / \
        3   2
       /     \  
      5       9 
     /         \
    6           7
Output: 8
Explanation:The maximum width existing in the fourth level with the length 8 (6,null,null,null,null,null,null,7).

Note: Answer will in the range of 32-bit signed integer.

 

这道题让我们求二叉树的最大宽度,根据题目中的描述可知,这里的最大宽度不是满树的时候的最大宽度,如果是那样的话,肯定是最后一层的结点数最多。这里的最大宽度应该是两个存在的结点中间可容纳的总的结点个数,中间的结点可以为空。那么其实只要我们知道了每一层中最左边和最右边的结点的位置,我们就可以算出这一层的宽度了。所以这道题的关键就是要记录每一层中最左边结点的位置,我们知道对于一棵完美二叉树,如果根结点是深度1,那么每一层的结点数就是 2n-1,那么每个结点的位置就是 [1, 2n-1] 中的一个,假设某个结点的位置是i,那么其左右子结点的位置可以直接算出来,为 2i 和 2i+1,可以自行带例子检验。由于之前说过,我们需要保存每一层的最左结点的位置,那么我们使用一个数组 start,由于数组是从0开始的,我们就姑且认定根结点的深度为0,不影响结果。我们从根结点进入,深度为0,位置为1,进入递归函数。首先判断,如果当前结点为空,那么直接返回,然后判断如果当前深度大于 start 数组的长度,说明当前到了新的一层的最左结点,我们将当前位置存入 start 数组中。然后我们用 idx - start[h] + 1 来更新结果 res。这里 idx 是当前结点的位置,start[h] 是当前层最左结点的位置。然后对左右子结点分别调用递归函数,注意左右子结点的位置可以直接计算出来,代码参见评论区二楼。我们也可以让递归函数直接返回最大宽度了,但是解题思路没有啥区别,代码参见评论区三楼。这两种方法之前都能通过 OJ,直到后来加了一个很极端的 test case,使得二者都整型溢出了 Signed Integer Overflow,原因是这里每层都只有1个结点,而我们代码中坐标每次都要乘以2的,所以到32层以后就直接溢出了。为了避免溢出的问题,需要做些优化,就是要统计每层的结点数,若该层只有一个结点,那么该层结点的坐标值重置为1,这样就可以避免溢出了。所以 DFS 的解法就不能用了,只能用层序遍历,迭代的方法来写,这里使用了队列 queue 来辅助运算,queue 里存的是一个 pair,结点和其当前位置,在进入新一层的循环时,首先要判断该层是否只有1个结点,是的话重置结点坐标位置,再将首结点的位置保存出来当作最左位置,然后对于遍历到的结点,都更新右结点的位置,遍历一层的结点后来计算宽度更新结果 res,参见代码如下:

 

class Solution {
public:
    int widthOfBinaryTree(TreeNode* root) {
        if (!root) return 0;
        int res = 0;
        queue<pair<TreeNode*,int>> q;
        q.push({root, 1});
        while (!q.empty()) {
            if (q.size() == 1) q.front().second = 1;
            int left = q.front().second, right = left, n = q.size();
            for (int i = 0; i < n; ++i) {
                auto t = q.front().first; 
                right = q.front().second; q.pop();
                if (t->left) q.push({t->left, right * 2});
                if (t->right) q.push({t->right, right * 2 + 1});
            }
            res = max(res, right - left + 1);
        }
        return res;
    }
};

 

Github 同步地址:

#662

 

参考资料:

https://leetcode.com/problems/maximum-width-of-binary-tree/

https://leetcode.com/problems/maximum-width-of-binary-tree/discuss/327721/cpp-bfs-solution

https://leetcode.com/problems/maximum-width-of-binary-tree/discuss/106654/javac-very-simple-dfs-solution

https://leetcode.com/problems/maximum-width-of-binary-tree/discuss/106645/cjava-bfsdfs3liner-clean-code-with-explanation

 

LeetCode All in One 题目讲解汇总(持续更新中...)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant