Practice: Merge K Sorted Lists

Problem: https://leetcode.com/problems/merge-k-sorted-lists/

Recognition reminder: you have k sorted linked lists and want one merged sorted list. You solved this in Week 6 with repeated pairwise merging; this week you redo it from the heap angle. This is the “merge sorted streams” shape: the next node in the answer is always the global minimum among the current front nodes of the lists, and a heap gives you that minimum in O(log k). Same problem, a different and very reusable lens.

Before you start (the five-beat rhythm)

  1. Your Pattern Card for this week is already written.
  2. Name the pattern aloud and write your approach as a plain-English comment before any code.
  3. Struggle floor: 25 minutes unaided. No hints, no AI, no Discuss tab.
  4. If stuck past the floor, ask the tutor for a hint. Six rungs, one per ask.
  5. Debrief in your commit message before moving to the next problem.

Your target

Fill these in yourself before you look at anyone else’s solution:

Target time complexity:  ____   (in terms of N, the total number of nodes, and k, the number of lists)
Target space complexity: ____

The heap idea: seed a heap with the head node of every non-empty list. Then repeatedly pop the smallest, append it to your result, and push that node’s successor (if it has one) from the same list. The heap never holds more than k entries (one per list), so each pop and push is O(log k), and you do one pair of them per node. That is the complexity to write down and compare against the pairwise-merge approach from Week 6.

There is one Python trap that this problem is the perfect place to learn. Your heap entries cannot be bare nodes, because a ListNode has no defined ordering and the heap has to compare entries. The standard entry is a tuple (value, list_index, node): value is what you sort by, and list_index is a tiebreaker that is always comparable. Think about why list_index alone is enough to break every tie before the heap ever has to look at the node: how many nodes from the same list are ever in the heap at the same time? Settle that in your head before you code, and put the answer in your debrief.

The interface you implement

Write a function merge_k_lists(lists) in a file named solution.py in this folder (your own work repo, not the course repo). The argument lists is a Python list of linked-list head nodes (each possibly None for an empty list), and you return the head node of the single merged sorted list (or None if there is nothing to merge). The node type is the usual singly linked list node:

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

The provided test defines this ListNode for you and includes small helpers to build a linked list from a Python list and to read one back, so your CASES can be written as plain lists of lists. Handle the empty cases: an empty outer list (no lists at all) and a list whose only entry is an empty list both produce an empty result.

Where your code goes

Write your solution in your own work repo (see getting-started.md), not in this folder. This folder ships only the problem spec and a provided-example test (tests/test_provided.py) so you can check the given cases locally before you submit to LeetCode’s judge. The judge is the oracle; the tutor will not confirm your answer by reading it.

Debrief (paste into your commit message)

1. What pattern did this turn out to be?
2. What was the trigger phrase or input shape that should have made me reach for it?
3. What was the time and space complexity, and what would dominate at scale?
4. What edge case would have broken my first attempt?
5. What would I do differently in three days when I see this cold?