[LeetCode] Add One Row to Tree 二叉樹中增加一行
Given the root of a binary tree, then value v
and depth d
, you need to add a row of nodes with value v
at the given depth d
. The root node is at depth 1.
The adding rule is: given a positive integer depth d
, for each NOT null tree nodes N
in depth d-1
, create two tree nodes with value v
as N's
left subtree root and right subtree root. And N's
d
is 1 that means there is no depth d-1 at all, then create a tree node with value v as the new root of the whole original tree, and the original tree is the new root's left subtree.Example 1:
Input: A binary tree as following: 4 / \ 2 6 / \ / 3 1 5 v = 1 d = 2 Output: 4 / \ 1 1 / \ 2 6 / \ / 3 1 5
Example 2:
Input: A binary tree as following: 4 / 2 / \ 3 1 v = 1 d = 3 Output: 4 / 2 / \ 1 1 / \ 3 1
Note:
- The given d is in range [1, maximum depth of the given tree + 1].
- The given binary tree has at least one tree node.
這道題讓我們給二叉樹增加一行,給了我們需要增加的值,還有需要增加的位置深度,題目中給的例子也比較能清晰的說明問題。但是漏了一種情況,那就是當d=1時,這該怎麼加?這時候就需要替換根結點了。其他情況的處理方法都一樣,這裡博主第一映像覺得應該用層序遍歷來做,沒遍歷完一層,d自減1,我們探測,當d==1時,那麼我們需要對於當前層的每一個結點,首先用臨時變數儲存其原有的左右子結點,然後新建值為v的左右子結點,將原有的左子結點連到新建的左子結點的左子結點上,將原有的右子結點連到新建的右子結點的右子結點,是不是很繞-.-|||。如果d不為1,那麼就是層序遍歷原有的排入佇列操作,記得當檢測到d為0時,直接返回,因為新增操作已經完成,沒有必要遍歷完剩下的結點,參見程式碼如下:
解法一:
class Solution { public: TreeNode* addOneRow(TreeNode* root, int v, int d) { if (!root) return NULL; if (d == 1) { TreeNode *newRoot = new TreeNode(v); newRoot->left = root; return newRoot; } queue<TreeNode*> q{{root}}; while (!q.empty()) { if (--d == 0) return root; int n = q.size(); for (int i = 0; i < n; ++i) { auto t = q.front(); q.pop(); if (d == 1) { TreeNode *left = t->left; TreeNode *right = t->right; t->left = new TreeNode(v); t->right = new TreeNode(v); t->left->left = left; t->right->right = right; } else { if (t->left) q.push(t->left); if (t->right) q.push(t->right); } } } return root; } };
雖然博主一貫的理念是二叉樹問題肯定首選遞迴來解,但是這道題博主剛開始以為遞迴沒法解,結果看了大神們的帖子,才發現自己還是圖樣圖森破,難道二叉樹的問題皆可遞迴?反正這道題是可以的,而且寫法so簡潔,乍一看上去,會有疑問,題目中明明d的範圍是從1開始的,為何要考慮d為0的情況,後來讀懂了整個解法後,才為原作者的聰慧歎服。這裡d的0和1,其實相當於一種flag,如果d為1的話,那麼將root連到新建的結點的左子結點上;反之如果d為0,那麼將root連到新建的結點的右子結點上,然後返回新建的結點。如果root存在且d大於1的話,那麼對root的左子結點呼叫遞迴函式,注意此時若d的值正好為2,那麼我們就不能直接減1,而是根據左右子結點的情況分別賦值1和0,這樣才能起到flag的作用嘛,叼的飛起,參見程式碼如下:
解法二:
class Solution { public: TreeNode* addOneRow(TreeNode* root, int v, int d) { if (d == 0 || d == 1) { TreeNode *newRoot = new TreeNode(v); (d ? newRoot->left : newRoot->right) = root; return newRoot; } if (root && d > 1) { root->left = addOneRow(root->left, v, d > 2 ? d - 1 : 1); root->right = addOneRow(root->right, v, d > 2 ? d - 1 : 0); } return root; } };
參考資料: