二叉树展开为链表
1.题目内容
给你二叉树的根结点 root ,请你将它展开为一个单链表:
- 展开后的单链表应该同样使用
TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。
- 展开后的单链表应该与二叉树先序遍历顺序相同。
示例 1:

1 2
| 输入:root = [1,2,5,3,4,null,6] 输出:[1,null,2,null,3,null,4,null,5,null,6]
|
示例 2:
示例 3:
提示:
- 树中结点数在范围
[0, 2000] 内
-100 <= Node.val <= 100
2.解法
(1)前序遍历
思路及算法
将二叉树展开为单链表之后,单链表中的节点顺序即为二叉树的前序遍历访问各节点的顺序。因此,可以对二叉树进行前序遍历,获得各节点被访问到的顺序。由于将二叉树展开为链表之后会破坏二叉树的结构,因此在前序遍历结束之后更新每个节点的左右子节点的信息,将二叉树展开为单链表。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| //Java class Solution { public void flatten(TreeNode root) { List<TreeNode> list = new ArrayList<TreeNode>(); preorderTraversal(root, list); int size = list.size(); for (int i = 1; i < size; i++) { TreeNode prev = list.get(i - 1), curr = list.get(i); prev.left = null; prev.right = curr; } }
public void preorderTraversal(TreeNode root, List<TreeNode> list) { if (root != null) { list.add(root); preorderTraversal(root.left, list); preorderTraversal(root.right, list); } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| //C++ class Solution { public: void flatten(TreeNode* root) { vector<TreeNode*> l; preorderTraversal(root, l); int n = l.size(); for (int i = 1; i < n; i++) { TreeNode *prev = l.at(i - 1), *curr = l.at(i); prev->left = nullptr; prev->right = curr; } }
void preorderTraversal(TreeNode* root, vector<TreeNode*> &l) { if (root != NULL) { l.push_back(root); preorderTraversal(root->left, l); preorderTraversal(root->right, l); } } };
|
复杂度分析
(2)前序遍历和展开同步进行
思路及算法
由于将节点展开之后会破坏二叉树的结构而丢失子节点的信息,因此前序遍历和展开为单链表分成了两步。能不能在不丢失子节点的信息的情况下,将前序遍历和展开为单链表同时进行?
之所以会在破坏二叉树的结构之后丢失子节点的信息,是因为在对左子树进行遍历时,没有存储右子节点的信息,在遍历完左子树之后才获得右子节点的信息。只要对前序遍历进行修改,在遍历左子树之前就获得左右子节点的信息,并存入栈内,子节点的信息就不会丢失,就可以将前序遍历和展开为单链表同时进行。
该做法不适用于递归实现的前序遍历,只适用于迭代实现的前序遍历。修改后的前序遍历的具体做法是,每次从栈内弹出一个节点作为当前访问的节点,获得该节点的子节点,如果子节点不为空,则依次将右子节点和左子节点压入栈内(注意入栈顺序)。
展开为单链表的做法是,维护上一个访问的节点 prev,每次访问一个节点时,令当前访问的节点为 curr,将 prev 的左子节点设为 null 以及将 prev 的右子节点设为 curr,然后将 curr 赋值给 prev,进入下一个节点的访问,直到遍历结束。需要注意的是,初始时 prev 为 null,只有在 prev 不为 null 时才能对 prev 的左右子节点进行更新。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| //Java class Solution { public void flatten(TreeNode root) { if (root == null) { return; } Deque<TreeNode> stack = new LinkedList<TreeNode>(); stack.push(root); TreeNode prev = null; while (!stack.isEmpty()) { TreeNode curr = stack.pop(); if (prev != null) { prev.left = null; prev.right = curr; } TreeNode left = curr.left, right = curr.right; if (right != null) { stack.push(right); } if (left != null) { stack.push(left); } prev = curr; } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| //C++ class Solution { public: void flatten(TreeNode* root) { if (root == nullptr) { return; } auto stk = stack<TreeNode*>(); stk.push(root); TreeNode *prev = nullptr; while (!stk.empty()) { TreeNode *curr = stk.top(); stk.pop(); if (prev != nullptr) { prev->left = nullptr; prev->right = curr; } TreeNode *left = curr->left, *right = curr->right; if (right != nullptr) { stk.push(right); } if (left != nullptr) { stk.push(left); } prev = curr; } } };
|
复杂度分析