[LeetCode] 662. Maximum Width of Binary Tree 二叉樹的最大寬度


 

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,那么每一層的結點數就是 2*n-1,那么每個結點的位置就是 [1, 2*n-1] 中的一個,假設某個結點的位置是i,那么其左右子結點的位置可以直接算出來,為 2*i 和 2*i+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 同步地址:

https://github.com/grandyang/leetcode/issues/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 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM