23. Merge K Sorted Lists
hardAsked at Juniper NetworksMerge k sorted linked lists into one sorted list efficiently. Juniper's control plane regularly merges sorted streams from multiple routing protocol tables (OSPF, BGP, IS-IS) into a unified RIB — a k-way merge with a min-heap is the production algorithm behind this operation.
By Alex Chen, Founder, InterviewChamp.AI · Last verified
Source citations
Public interview reports confirming this problem appears in Juniper Networks loops.
- Glassdoor (2026-Q1)— Cited in Juniper SWE onsite reports as a high-difficulty problem in routing and platform team interviews.
- Blind (2025-12)— Juniper interview threads list Merge K Sorted Lists as the canonical hard linked-list problem with direct networking relevance.
Problem
You are given an array of k linked-lists lists, each linked-list is sorted in ascending order. Merge all the linked-lists into one sorted linked-list and return it.
Constraints
k == lists.length0 <= k <= 10^40 <= lists[i].length <= 500−10^4 <= lists[i][j] <= 10^4lists[i] is sorted in ascending order.The sum of lists[i].length will not exceed 10^4.
Examples
Example 1
lists = [[1,4,5],[1,3,4],[2,6]][1,1,2,3,4,4,5,6]Explanation: Three sorted lists merged into one.
Example 2
lists = [][]Explanation: Empty input.
Example 3
lists = [[]][]Explanation: Single empty list.
Approaches
1. Divide and conquer (pair-wise merges)
Reduce k lists to 1 by repeatedly merging pairs. Each pass halves the number of lists. Uses the O(m+n) two-list merge as a primitive.
- Time
- O(N log k) where N = total nodes
- Space
- O(log k) call stack
function mergeTwoLists(l1, l2) {
const dummy = { next: null };
let curr = dummy;
while (l1 && l2) {
if (l1.val <= l2.val) { curr.next = l1; l1 = l1.next; }
else { curr.next = l2; l2 = l2.next; }
curr = curr.next;
}
curr.next = l1 || l2;
return dummy.next;
}
function mergeKLists(lists) {
if (!lists || lists.length === 0) return null;
let interval = 1;
while (interval < lists.length) {
for (let i = 0; i + interval < lists.length; i += interval * 2) {
lists[i] = mergeTwoLists(lists[i], lists[i + interval]);
}
interval *= 2;
}
return lists[0];
}Tradeoff: O(N log k) time, O(1) extra space (excluding output). The divide-and-conquer insight: each node participates in O(log k) merges, giving the log k factor.
2. Min-heap — direct k-way merge
Use a min-heap (priority queue) seeded with the first node of each list. Repeatedly extract the minimum, append to result, and push the next node from the same list.
- Time
- O(N log k)
- Space
- O(k) heap
// JavaScript lacks a built-in heap; simulate with a sorted structure
// In a real interview, implement a MinHeap or use a language with PriorityQueue
function mergeKLists(lists) {
// Simulated via sorted array insertion (interview pseudocode)
// Production: use a proper MinHeap with O(log k) push/pop
const heap = [];
const push = (node) => {
if (!node) return;
heap.push(node);
heap.sort((a, b) => a.val - b.val); // O(k log k) per op — use real heap in prod
};
for (const head of lists) push(head);
const dummy = { next: null };
let curr = dummy;
while (heap.length) {
const node = heap.shift();
curr.next = node;
curr = curr.next;
push(node.next);
}
return dummy.next;
}Tradeoff: O(N log k) with a real min-heap. In JavaScript, implement a binary heap class or note that the sort simulation is for illustration only. The min-heap is the canonical approach in most languages with built-in priority queues (Java PriorityQueue, Python heapq, C++ std::priority_queue).
Juniper Networks-specific tips
Lead with the divide-and-conquer approach in JavaScript since a built-in heap is not available. In a Juniper interview, mention both approaches and their space tradeoffs: divide-and-conquer uses O(log k) stack space while the heap uses O(k). The O(N log k) time complexity derivation is worth explaining: N total nodes, each participating in O(log k) merge rounds. Connect directly to networking: 'Junos merges route streams from OSPF areas, BGP peers, and static routes into a unified RIB — this is a k-way merge.'
Common mistakes
- Using a sequential merge (merge list 0 with 1, result with 2, etc.) — O(kN) time, not O(N log k).
- Not handling empty lists or null heads in the heap — push(node.next) can push null.
- Forgetting the k=0 and k=1 edge cases.
- Not disconnecting curr.next before returning — left-over next pointers from original lists can corrupt the result.
Follow-up questions
An interviewer at Juniper Networks may pivot to one of these next:
- Sort a Linked List (LC 148) — merge sort applied to a single linked list.
- Find K-th Smallest Element Across K Sorted Arrays — same heap approach applied to arrays.
- How would you handle merging k sorted streams in a distributed system where each stream arrives from a different routing protocol daemon?
Solve it now
Free. No sign-up. Python and JavaScript run instantly in your browser.
FAQ
Why is the naive sequential merge O(kN) not O(N log k)?
Merging lists one at a time means the first list participates in k-1 merge rounds. Its N/k nodes are each touched O(k) times. Total cost = sum over k rounds = O(kN) in the worst case.
How does divide-and-conquer achieve O(N log k)?
After sorting, each node participates in exactly log k merge rounds (the number of pairing levels). Total cost = N nodes * log k rounds = O(N log k).
When would you prefer the heap over divide-and-conquer?
When the k lists arrive incrementally (streaming) and you cannot store all list heads up front. The heap naturally processes nodes in a streaming fashion.
Practice these live with InterviewChamp.AI
Drill Merge K Sorted Lists and other Juniper Networks interview questions under real-loop conditions with instant feedback on your reasoning, complexity claims, and code.
Practice these live with InterviewChamp.AI →