Flatten Binary Tree to Linked List
Question: https://leetcode.com/problems/flatten-binary-tree-to-linked-list/
题目:
Given a binary tree, flatten it to a linked list in-place.
For example,
Given
1 / \ 2 5 / \ \ 3 4 6
The flattened tree should look like:
1 \ 2 \ 3 \ 4 \ 5 \ 6
Hints:
If you notice carefully in the flattened tree, each node's right child points to the next node of a pre-order traversal.
Solution 1: 一般性的 Binary Tree Preorder Traversal
1 public void flatten(TreeNode root) { 2 if(root == null) { 3 return; 4 } 5 6 ArrayList<TreeNode> list = new ArrayList<>(); 7 helper(root, list); 8 9 list.get(0).left = null; 10 for(int i = 1; i < list.size(); i++) { 11 list.get(i).left = null; 12 list.get(i-1).right = list.get(i); 13 } 14 } 15 16 private void helper(TreeNode root, ArrayList<TreeNode> list) { 17 if(root == null) { 18 return; 19 } 20 21 list.add(root); 22 helper(root.left, list); 23 helper(root.right, list); 24 }
Sulotion 2: Refer from Code Ganker
1 public void flatten(TreeNode root) { 2 if(root == null) { 3 return; 4 } 5 6 ArrayList<TreeNode> list = new ArrayList<>(); 7 list.add(null); 8 helper(root, list); 9 } 10 11 private void helper(TreeNode root, ArrayList<TreeNode> list) { 12 if(root == null) { 13 return; 14 } 15 16 TreeNode right = root.right; // Attention here 17 if(list.get(0) != null) { 18 list.get(0).left = null; 19 list.get(0).right = root; 20 } 21 22 list.set(0, root); 23 helper(root.left, list); 24 helper(right, list); 25 }
这里的 ArrayList 是 Code Ganker 中经常使用的处理方式,实质就是一个 Reference to an object with updated Instance variable. Wrapper Class with field variable 也可以实现这项功能。
这里的 list variable 一直只包含一个 TreeNode,这个 TreeNode 是已经得到、不断被更新的 flattened LinkedList 的最后一个 Element。
Attention:
- Line #16: 此刻的 root.right 必须使用 local variable 保存其 Reference,因为 经过 Line #23 之后 root.right 已经是 原本的 root.left。
- Line #23 与 #24 中的 list 所指向的 TreeNode 是不同的。
- Line #23 中 list 指向的是 TreeNode root
- Line #24 中 list 指向的是 Preorder 中 TreeNode right 的前一个 TreeNode,也就是已经处理的 flattened LinkedList 的最后一个 Element。
- 该处也是 使用 List 来包含 TreeNode,而不是直接传递 TreeNode prev 的原因
下面是 试图 采用 TreeNode prev 来代替 ArrayList<TreeNode> list 的错误代码。错误原因,上面分析和下面的代码中已经详述:
1 public class Solution { 2 public void flatten(TreeNode root) { 3 if(root == null) { 4 return; 5 } 6 7 helper(root, null); 8 } 9 10 private void helper(TreeNode root, TreeNode prev) { 11 if(root == null) { 12 return; 13 } 14 15 TreeNode right = root.right; 16 if(prev != null) { 17 prev.right = root; 18 prev.left = null; 19 } 20 21 prev = root; 22 helper(root.left, prev); 23 helper(right, prev); // 这里的 prev 仍是 root,实际上应该使用 更新过得 prev 24 } 25 }
Solution 3: 使用 field variable TreeNode prev 来代替 ArrayList<TreeNode> list
1 public class Solution { 2 // field variable to replace ArrayList<TreeNode> 3 public TreeNode prev = null; 4 5 public void flatten(TreeNode root) { 6 if(root == null) { 7 return; 8 } 9 10 helper(root); 11 } 12 13 private void helper(TreeNode root) { 14 if(root == null) { 15 return; 16 } 17 18 TreeNode right = root.right; 19 if(prev != null) { 20 prev.right = root; 21 prev.left = null; 22 } 23 24 prev = root; 25 helper(root.left); 26 helper(right); 27 } 28 }