Flattening a Linked List

Solve this Problem
Hard20–25 min
Topics
Companies
Practice:GFG ↗
Picture a collection of lists, each one already sorted, gathered together in some fixed order. Flatten every one of them into a single list that's still fully sorted, with every value from every original list included exactly once. This is the same shape as merging k sorted lists — it just arrives framed as separate sorted sub-lists that need combining rather than nodes with an extra pointer. Splitting the collection in half, recursively flattening each half down to one sorted list, and then merging those two results with a standard two-pointer splice keeps the total work proportional to N log k instead of degrading toward N times k if the lists were folded in one at a time.

Test Case 1:

Input:lists = [[5, 10], [2, 7], [1, 9]]
Output:[1, 2, 5, 7, 9, 10]
Explanation:Every value from all 3 already-sorted lists, merged into one fully sorted list.

Test Case 2:

Input:lists = [[3, 6, 9]]
Output:[3, 6, 9]
Explanation:A single list has nothing else to merge with.

Test Case 3:

Input:lists = [[], []]
Output:[]
Explanation:Every list is empty — nothing to flatten.

Constraints

  • 1 ≤ number of top-level lists (k) ≤ 50
  • 0 ≤ nodes per list ≤ 20
  • -1000 ≤ node value ≤ 1000
  • Each individual list is already sorted in increasing order
🚀

Try the Dry Run

Don't just read the solution — watch it execute, one step at a time.

Approach & Solutions

Brute Force — Collect Every Value, Sort, Rebuild

Good

Walk every list in turn, copying every value into one array. Sort that array from scratch, then build a brand-new list from it. Correct, but it throws away the fact that each list was already individually sorted — it re-sorts everything as if the values had arrived in no particular order at all.

TimeO(N log N), where N is the total number of nodes across every list
SpaceO(N)
1// Node definition used in this problem: 2// class Node { 3// int val; 4// Node next; 5// } 6 7class Solution { 8 public Node flatten(List<Node> lists) { 9 List<Integer> vals = new ArrayList<>(); 10 for (Node head : lists) { 11 Node curr = head; 12 while (curr != null) { 13 vals.add(curr.val); 14 curr = curr.next; 15 } 16 } 17 Collections.sort(vals); 18 Node dummy = new Node(0); 19 Node tail = dummy; 20 for (int v : vals) { 21 tail.next = new Node(v); 22 tail = tail.next; 23 } 24 return dummy.next; 25 } 26}

Optimal — Divide and Conquer, Pairwise Merge

Optimal

Merging two already-sorted lists is a solved problem — the trick is reducing many lists down to that. Split the array of lists in half, recursively flatten each half down to a single sorted list, then merge those two results together with a standard two-pointer splice. Halving the problem at every level keeps the total work O(N log k), instead of the O(N·k) that merging the lists one at a time into a growing result would cost.

TimeO(N log k), where N is the total number of nodes and k is the number of lists
SpaceO(log k) recursion stack
1// Node definition used in this problem: 2// class Node { 3// int val; 4// Node next; 5// } 6 7class Solution { 8 public Node flatten(List<Node> lists) { 9 return merge(lists, 0, lists.size() - 1); 10 } 11 12 private Node merge(List<Node> lists, int lo, int hi) { 13 if (lo > hi) { 14 return null; 15 } 16 if (lo == hi) { 17 return lists.get(lo); 18 } 19 int mid = lo + (hi - lo) / 2; 20 Node left = merge(lists, lo, mid); 21 Node right = merge(lists, mid + 1, hi); 22 return mergeTwoLists(left, right); 23 } 24 25 private Node mergeTwoLists(Node list1, Node list2) { 26 Node dummy = new Node(0); 27 Node tail = dummy; 28 while (list1 != null && list2 != null) { 29 if (list1.val <= list2.val) { 30 tail.next = list1; 31 list1 = list1.next; 32 } else { 33 tail.next = list2; 34 list2 = list2.next; 35 } 36 tail = tail.next; 37 } 38 tail.next = (list1 != null) ? list1 : list2; 39 return dummy.next; 40 } 41}

Related Problems