Binary TreesProblem 18 of 35
Convert Binary tree into Doubly Linked List
Problem Statement
Given a binary tree, convert it to a doubly linked list (DLL) in-place. The left pointer of the tree node should act as the previous pointer of DLL, and the right pointer should act as the next pointer. The DLL should follow the inorder traversal of the tree.
Example:
Input:
10
/ \
5 20
/ \ / \
3 8 15 25
Output DLL: 3 <-> 5 <-> 8 <-> 10 <-> 15 <-> 20 <-> 25
Approach 1: Using Inorder Traversal with Array
Intuition
Perform inorder traversal, store all nodes in an array, then link them together.
Algorithm
- Perform inorder traversal and collect all nodes
- Link each node to its neighbors in the array
- First node's prev = null, last node's next = null
java
import java.util.*;
class TreeNode {
int val;
TreeNode left, right;
TreeNode(int x) { val = x; }
}
public class Solution {
private void inorder(TreeNode root, List<TreeNode> nodes) {
if (root == null) return;
inorder(root.left, nodes);
nodes.add(root);
inorder(root.right, nodes);
}
public TreeNode binaryTreeToDLL(TreeNode root) {
if (root == null) return null;
List<TreeNode> nodes = new ArrayList<>();
inorder(root, nodes);
// Link nodes
for (int i = 0; i < nodes.size(); i++) {
nodes.get(i).left = (i > 0) ? nodes.get(i - 1) : null;
nodes.get(i).right = (i < nodes.size() - 1) ? nodes.get(i + 1) : null;
}
return nodes.get(0); // Head of DLL
}
}Complexity Analysis
- Time Complexity: O(n) - Inorder traversal + linking
- Space Complexity: O(n) - Array stores all nodes
Approach 2: Optimal (In-place Conversion)
Intuition
During inorder traversal, maintain a pointer to the previously visited node. Link the previous node's right to current, and current's left to previous.
Algorithm
- Track the previous node during inorder traversal
- Link prev.right = current and current.left = prev
- Update prev to current after processing
- Return the leftmost node as head
java
class TreeNode {
int val;
TreeNode left, right;
TreeNode(int x) { val = x; }
}
public class Solution {
private TreeNode prev;
private TreeNode head;
private void inorder(TreeNode root) {
if (root == null) return;
// Process left subtree
inorder(root.left);
// Process current node
if (prev == null) {
// First node - this is the head
head = root;
} else {
// Link previous node with current
prev.right = root;
root.left = prev;
}
prev = root;
// Process right subtree
inorder(root.right);
}
public TreeNode binaryTreeToDLL(TreeNode root) {
if (root == null) return null;
prev = null;
head = null;
inorder(root);
return head;
}
public TreeNode binaryTreeToCircularDLL(TreeNode root) {
if (root == null) return null;
prev = null;
head = null;
inorder(root);
// Make it circular
head.left = prev;
prev.right = head;
return head;
}
}Complexity Analysis
- Time Complexity: O(n) - Single inorder traversal
- Space Complexity: O(h) - Recursion stack, where h is height
Approach 3: Morris Traversal (True O(1) Space)
Intuition
Use Morris traversal to achieve O(1) space (ignoring output). This modifies the tree during traversal but restores it while building the DLL.
Algorithm
- Use Morris inorder traversal
- Track prev and head as before
- Link nodes during the traversal
Complexity Analysis
- Time Complexity: O(n) - Each edge traversed at most twice
- Space Complexity: O(1) - No extra space (in-place)
Utility: Print DLL
Key Takeaways
- Inorder traversal naturally gives sorted DLL for BST
- Key insight: Use prev pointer to link nodes during traversal
- Three approaches: Array (easy), recursive (optimal), Morris (space-optimal)
- Circular DLL: Just connect head and tail at the end
- left pointer = prev, right pointer = next in the DLL
- This is a popular interview question combining tree and linked list concepts
- Same technique can be used to flatten BST to sorted linked list