Print a binary tree in an m*n 2D string array following these rules:
- The row number
m
should be equal to the height of the given binary tree. - The column number
n
should always be an odd number. - The root node's value (in string format) should be put in the exactly middle of the first row it can be put. The column and the row where the root node belongs will separate the rest space into two parts (left-bottom part and right-bottom part). You should print the left subtree in the left-bottom part and print the right subtree in the right-bottom part. The left-bottom part and the right-bottom part should have the same size. Even if one subtree is none while the other is not, you don't need to print anything for the none subtree but still need to leave the space as large as that for the other subtree. However, if two subtrees are none, then you don't need to leave space for both of them.
- Each unused space should contain an empty string
""
. - Print the subtrees following the same rules.
Example 1:
Input: 1 / 2 Output: [["", "1", ""], ["2", "", ""]]
Example 2:
Input: 1 / \ 2 3 \ 4 Output: [["", "", "", "1", "", "", ""], ["", "2", "", "", "", "3", ""], ["", "", "4", "", "", "", ""]]
Example 3:
Input: 1 / \ 2 5 / 3 / 4 Output: [["", "", "", "", "", "", "", "1", "", "", "", "", "", "", ""] ["", "", "", "2", "", "", "", "", "", "", "", "5", "", "", ""] ["", "3", "", "", "", "", "", "", "", "", "", "", "", "", ""] ["4", "", "", "", "", "", "", "", "", "", "", "", "", "", ""]]
Note: The height of binary tree is in the range of [1, 10].
這道題給了我們一棵二叉樹,讓我們以數組的形式打印出來。數組每一行的寬度是二叉樹的最底層數所能有的最多結點數,存在的結點需要填入到正確的位置上。那么這道題我們就應該首先要確定返回數組的寬度,由於寬度跟數組的深度有關,所以我們首先應該算出二叉樹的最大深度,直接寫一個子函數返回這個最大深度,從而計算出寬度。下面就是要遍歷二叉樹從而在數組中加入結點值。我們先來看第一行,由於根結點只有一個,所以第一行只需要插入一個數字,不管這一行多少個位置,我們都是在最中間的位置插入結點值。下面來看第二行,我們仔細觀察可以發現,如果我們將這一行分為左右兩部分,那么插入的位置還是在每一部分的中間位置,這樣我們只要能確定分成的部分的左右邊界位置,就知道插入結點的位置了,所以應該是使用分治法的思路。在遞歸函數中,如果當前node不存在或者當前深度超過了最大深度直接返回,否則就給中間位置賦值為結點值,然后對於左子結點,范圍是左邊界到中間位置,調用遞歸函數,注意當前深度加1;同理對於右子結點,范圍是中間位置加1到右邊界,調用遞歸函數,注意當前深度加1,參見代碼如下:
解法一:
class Solution { public: vector<vector<string>> printTree(TreeNode* root) { int h = getHeight(root), w = pow(2, h) - 1; vector<vector<string>> res(h, vector<string>(w, "")); helper(root, 0, w - 1, 0, h, res); return res; } void helper(TreeNode* node, int i, int j, int curH, int height, vector<vector<string>>& res) { if (!node || curH == height) return; res[curH][(i + j) / 2] = to_string(node->val); helper(node->left, i, (i + j) / 2, curH + 1, height, res); helper(node->right, (i + j) / 2 + 1, j, curH + 1, height, res); } int getHeight(TreeNode* node) { if (!node) return 0; return 1 + max(getHeight(node->left), getHeight(node->right)); } };
下面這種方法是層序遍歷二叉樹,使用了兩個輔助隊列來做,思路都一樣,只不過是迭代的寫法而已,關鍵還是在於左右邊界的處理上,參見代碼如下:
解法二:
class Solution { public: vector<vector<string>> printTree(TreeNode* root) { int h = getHeight(root), w = pow(2, h) - 1, curH = -1; vector<vector<string>> res(h, vector<string>(w, "")); queue<TreeNode*> q{{root}}; queue<pair<int, int>> idxQ{{{0, w - 1}}}; while (!q.empty()) { int n = q.size(); ++curH; for (int i = 0; i < n; ++i) { auto t = q.front(); q.pop(); auto idx = idxQ.front(); idxQ.pop(); if (!t) continue; int left = idx.first, right = idx.second; int mid = left + (right - left) / 2; res[curH][mid] = to_string(t->val); q.push(t->left); q.push(t->right); idxQ.push({left, mid}); idxQ.push({mid + 1, right}); } } return res; } int getHeight(TreeNode* node) { if (!node) return 0; return 1 + max(getHeight(node->left), getHeight(node->right)); } };
參考資料:
https://discuss.leetcode.com/topic/98381/java-recursive-solution
https://discuss.leetcode.com/topic/98503/java-iterative-level-order-traversal-with-queue