Medium!
題目描述:
給定一個二叉樹,原地將它展開為鏈表。
例如,給定二叉樹
1 / \ 2 5 / \ \ 3 4 6
將其展開為:
1 \ 2 \ 3 \ 4 \ 5 \ 6
解題思路:
這道題要求把二叉樹展開成鏈表,根據展開后形成的鏈表的順序分析出是使用先序遍歷,那么只要是數的遍歷就有遞歸和非遞歸的兩種方法來求解,這里我們也用兩種方法來求解。
首先來看遞歸版本的,思路是先利用DFS的思路找到最左子節點,然后回到其父節點,把其父節點和右子節點斷開,將原左子結點連上父節點的右子節點上,然后再把原右子節點連到新右子節點的右子節點上,然后再回到上一父節點做相同操作。
C++解法一:
1 // Recursion 2 class Solution { 3 public: 4 void flatten(TreeNode *root) { 5 if (!root) return; 6 if (root->left) flatten(root->left); 7 if (root->right) flatten(root->right); 8 TreeNode *tmp = root->right; 9 root->right = root->left; 10 root->left = NULL; 11 while (root->right) root = root->right; 12 root->right = tmp; 13 } 14 };
例如,對於下面的二叉樹,上述算法的變換的過程如下:
1 / \ 2 5 / \ \ 3 4 6 1 / \ 2 5 \ \ 3 6 \ 4 1 \ 2 \ 3 \ 4 \ 5 \ 6
下面我們再來看非迭代版本的實現,這個方法是從根節點開始出發,先檢測其左子結點是否存在,如存在則將根節點和其右子節點斷開,將左子結點及其后面所有結構一起連到原右子節點的位置,把原右子節點連到原左子結點最后面的右子節點之后。
C++解法二:
1 // Non-recursion 2 class Solution { 3 public: 4 void flatten(TreeNode *root) { 5 TreeNode *cur = root; 6 while (cur) { 7 if (cur->left) { 8 TreeNode *p = cur->left; 9 while (p->right) p = p->right; 10 p->right = cur->right; 11 cur->right = cur->left; 12 cur->left = NULL; 13 } 14 cur = cur->right; 15 } 16 } 17 };
例如,對於下面的二叉樹,上述算法的變換的過程如下:
1 / \ 2 5 / \ \ 3 4 6 1 \ 2 / \ 3 4 \ 5 \ 6 1 \ 2 \ 3 \ 4 \ 5 \ 6
前序迭代解法如下:
C++解法三:
1 class Solution { 2 public: 3 void flatten(TreeNode* root) { 4 if (!root) return; 5 stack<TreeNode*> s; 6 s.push(root); 7 while (!s.empty()) { 8 TreeNode *t = s.top(); s.pop(); 9 if (t->left) { 10 TreeNode *r = t->left; 11 while (r->right) r = r->right; 12 r->right = t->right; 13 t->right = t->left; 14 t->left = NULL; 15 } 16 if (t->right) s.push(t->right); 17 } 18 } 19 };
此題還可以延伸到用中序,后序,層序的遍歷順序來展開原二叉樹,分別又有其對應的遞歸和非遞歸的方法,有興趣的童鞋可以自行實現。