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 };
此题还可以延伸到用中序,后序,层序的遍历顺序来展开原二叉树,分别又有其对应的递归和非递归的方法,有兴趣的童鞋可以自行实现。