Flatten the Tree Into a Right-Leaning Chain
Solve this ProblemYou are given the root of a binary tree. Rearrange it in place — reusing the same nodes — into a "chain" that leans to the right: every node has no left child, and its right child is the node that comes next in the pre-order traversal of the original tree (node, then its left subtree, then its right subtree). Return the root of the rearranged tree.
You could record the pre-order in a list and then relink the nodes, but the rearrangement can also be done with a single pointer walking down the chain, splicing each right subtree behind the last node of the left subtree.
Test Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
0 ≤ number of nodes ≤ 100 - ◆
−100 ≤ node.val ≤ 100 - ◆
The tree is given as its root node (null for an empty tree); each node has a val, a left child and a right child - ◆
Rearrange the tree IN PLACE (reuse the same nodes) so that every node has no left child and its right child is the next node in the pre-order of the original tree (node, then its left subtree, then its right subtree). Return the root. The result is checked as a level-order list
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
Approach & Solutions
Brute Force — Collect the Pre-Order, Then Re-Link the Nodes
GoodFirst record every node in pre-order (node, then left subtree, then right subtree) in a list — nothing is changed yet, so the traversal is not disturbed by relinking. Then go through the list and rewire each node: its left child becomes null and its right child becomes the next node in the list (the last node's right child is null). It is easy to get right, but the list of all n nodes costs O(n) extra space; time is O(n).
O(n)O(n)1class Solution {
2 public TreeNode flattenInPreorder(TreeNode root) {
3 List<TreeNode> order = new ArrayList<>();
4 collect(root, order);
5 for (int i = 0; i < order.size(); i++) {
6 order.get(i).left = null;
7 order.get(i).right = i + 1 < order.size() ? order.get(i + 1) : null;
8 }
9 return root;
10 }
11
12 private void collect(TreeNode node, List<TreeNode> order) {
13 if (node == null) return;
14 order.add(node);
15 collect(node.left, order);
16 collect(node.right, order);
17 }
18}Optimal — Splice the Right Subtree Onto the Left Subtree's Last Node
OptimalWalk down the chain being built with a pointer cur. If cur has a left subtree, find the LAST node of that subtree in pre-order — the rightmost node, reached by going right until you cannot — and hang cur's current right subtree from it: in pre-order that whole right subtree comes right after the left subtree. Then move the left subtree into the right slot and set left to null. Step to cur's right child and repeat. Every node is spliced at most once and each rightmost search only walks parts of the tree that are never searched again, so it is O(n) time and needs no list and no recursion: O(1) extra space.
O(n)O(1)1class Solution {
2 public TreeNode flattenInPreorder(TreeNode root) {
3 TreeNode cur = root;
4 while (cur != null) {
5 if (cur.left != null) {
6 TreeNode tail = cur.left;
7 while (tail.right != null) tail = tail.right;
8 tail.right = cur.right;
9 cur.right = cur.left;
10 cur.left = null;
11 }
12 cur = cur.right;
13 }
14 return root;
15 }
16}