DEV Community

Ruairí O'Brien
Ruairí O'Brien

Posted on

Day 24 - Merge k Sorted Lists

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.

Example 1:

Input: lists = [[1,4,5],[1,3,4],[2,6]]
Output: [1,1,2,3,4,4,5,6]
Explanation: The linked-lists are:
[
  1->4->5,
  1->3->4,
  2->6
]
merging them into one sorted list:
1->1->2->3->4->4->5->6
Enter fullscreen mode Exit fullscreen mode

Example 2:

Input: lists = []
Output: []
Enter fullscreen mode Exit fullscreen mode

Example 3:

Input: lists = [[]]
Output: []
Enter fullscreen mode Exit fullscreen mode

Constraints:

  • k == lists.length
  • 0 <= k <= 10^4
  • 0 <= lists[i].length <= 500
  • -10^4 <= lists[i][j] <= 10^4
  • lists[I] is sorted in ascending order.
  • The sum of lists[i].length won't exceed 10^4.

Tests

import pytest
from .util import toListNode, toList
from .Day24_MergeKSortedLists import Solution

s = Solution()


@pytest.mark.parametrize(
    "lists,expected",
    [([[1, 4, 5], [1, 3, 4], [2, 6]], [1, 1, 2, 3, 4, 4, 5, 6]), ([], []), ([[]], [])],
)
def test_merge_k_lists(lists, expected):
    assert toList(s.mergeKLists(list(map(lambda x: toListNode(x), lists)))) == expected

@pytest.mark.parametrize(
    "lists,expected",
    [([[1, 4, 5], [1, 3, 4], [2, 6]], [1, 1, 2, 3, 4, 4, 5, 6]), ([], []), ([[]], [])],
)
def test_merge_k_lists2(lists, expected):
    assert toList(s.mergeKLists2(list(map(lambda x: toListNode(x), lists)))) == expected
Enter fullscreen mode Exit fullscreen mode

Solution

from typing import List
from .util import ListNode
from queue import PriorityQueue


def mergeTwoLists(l1: ListNode, l2: ListNode) -> ListNode:
    head = ListNode()
    current = head
    while l1 and l2:
        if l1.val <= l2.val:
            current.next = l1
            l1 = l1.next
        else:
            current.next = l2
            l2 = l1
            l1 = current.next.next
        current = current.next
    current.next = l2 if l2 else l1
    return head.next


class Solution:
    def build_queue(self, lists: List[ListNode]) -> PriorityQueue:
        q = PriorityQueue()
        for l in lists:
            if l:
                q.put((l.val, l))
        return q

    def mergeKLists2(self, lists: List[ListNode]) -> ListNode:
        head = ListNode()
        current = head
        q = self.build_queue(lists)

        while not q.empty():
            val, list_node = q.get()
            current.next = ListNode(val)
            current = current.next
            next_node = list_node.next
            if next_node:
                q.put((next_node.val, next_node))

        return head.next

    def mergeKLists(self, lists: List[ListNode]) -> ListNode:
        k = len(lists)
        if k == 0:
            return None

        step = 1
        while step < k:
            for i in range(0, k - step, step * 2):
                lists[i] = mergeTwoLists(lists[i], lists[i + step])
            step *= 2

        return lists[0]

Enter fullscreen mode Exit fullscreen mode

Analysis

Alt Text

Commentary

Link to code

This seemed like a good place to use a PriorityQueue to me but I couldn't get it to work in leetcode as the ListNode class did not implement __gt__or __lt__. I have left an example in the code called mergeKLists2.

The solution I went with was kind of cheating. I more or less copied the solution from Day 4. I improved it a little but basically we are breaking the problem down into merging 2 sorted lists.

We merge in steps to basically merge in pairs. Eventually you get all lists merged.

The runtime is about O(n log k) where k = len(lists). We don't use up any extra space.

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

Top comments (0)

Billboard image

Create up to 10 Postgres Databases on Neon's free plan.

If you're starting a new project, Neon has got your databases covered. No credit cards. No trials. No getting in your way.

Try Neon for Free →

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay