Flattening a Linked List
Solve this ProblemTest Case 1:
Test Case 2:
Test Case 3:
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
GoodWalk 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.
O(N log N), where N is the total number of nodes across every listO(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
OptimalMerging 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.
O(N log k), where N is the total number of nodes and k is the number of listsO(log k) recursion stack1// 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}