# 23. Merge k Sorted Lists

**<font color=red>难度: Hard</font>**

## 刷题内容

> 原题连接

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

> 内容描述

```
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

Example:

Input:
[
  1->4->5,
  1->3->4,
  2->6
]
Output: 1->1->2->3->4->4->5->6
```

## 解题方案

> 思路 1


看到思路有heap，similar question有ugly number|| -> 这个是用heapq来解决的

那么就用heap吧？ heapsort

最简单的做法是只要每个list里面还有node，就把他们扔到minheap里面去，然后再把minheap pop，一个一个node连起来，听起来时间复杂度和空间复杂度都蛮高的。
直接merge必然是不好的，因为没有利用有序这个点，应该做的是每次取来一个，然后再把应该的下一个放入

写到这里瞬间明白和ugly number ii像的点了，甚至感觉跟find in sorted matrix ii也像

beats 96.26%

```python
class Solution(object):
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        from heapq import heappush, heappop
        nodes_pool = []
        dummy = cur = ListNode(-1)
        for head in lists:
            if head:
                heappush(nodes_pool, [head.val, head])
        while nodes_pool:
            smallest_node = heappop(nodes_pool)[1]
            cur.next = smallest_node
            cur = cur.next
            if smallest_node.next:
                heappush(nodes_pool, [smallest_node.next.val, smallest_node.next])
        return dummy.next
```

但是上面这个程序只能在python2里面用，如果在python3里面会报错：```TypeError: unorderable types: ListNode() < ListNode()```，
这是因为python3里面ListNode类型不能用于order了

因此对于python3我修改了一下程序，多用了一个dict来存放对应的node，这样就可以达到相同的效果了，见下面：

beats 96.50% 

```python
class Solution:
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        from heapq import heappush, heappop
        node_pools = []
        lookup = collections.defaultdict(list)
        for head in lists:
            if head:
                heappush(node_pools, head.val)
                lookup[head.val].append(head)
        dummy = cur = ListNode(None)
        while node_pools:
            smallest_val = heappop(node_pools)
            smallest_node = lookup[smallest_val].pop(0)
            cur.next = smallest_node
            cur = cur.next
            if smallest_node.next:
                heappush(node_pools, smallest_node.next.val)
                lookup[smallest_node.next.val].append(smallest_node.next)
        return dummy.next
```




## Follow up

> 问题描述

```
一个double array length为n，有k个区间，n >> k，每个区间是单调递增的
比如 [2.3, 5, 8.4, 3, 5, 1, 3, 9]，这里k是3，三个区间是[2.3, 5, 8.4]，[3, 5], [1,3,9]
要求输出sort好的array
比如 [1,2.3,3,3,5,5,8.4,9]
```

## 解题方案

> 思路 1

跟上面一样的思路，维护一个当前num pool就行了

```python
class Solution(object):
    def mergeKLists(self, nums, k):
        """
        :type list: int
        :rtype: list
        """
        num_pool = []  # current nums we are comparing
        interval_idx = []  # current k interval
        start, end = 0, 0
        for i in range(len(nums)-1):
            if nums[i] > nums[i+1]:
                end = i
                interval_idx.append([start, end])
                start = i+1
        interval_idx.append([start, len(nums)-1])
        # record which start is invalid in arr_idx
        invalid_interval_idx = set()
        res = []
        while len(invalid_interval_idx) != k:
            for i in range(len(interval_idx)):
                # we have to make sure start <= end
                if interval_idx[i][0] <= interval_idx[i][1]:
                    num_pool.append(nums[interval_idx[i][0]])
                    interval_idx[i][0] += 1
                else:
                    invalid_interval_idx.add(i)
            num_pool.sort()
            # begin to handle current k (maybe) nums
            for i in range(len(num_pool)):
                res.append(num_pool[i])
            num_pool = []
        return res
```


写一下测试用例

```python
import unittest


class TestSolution(unittest.TestCase):
    def test_none_0(self):
        nums = [2.3, 5, 8.4, 3, 5, 1, 3, 9]
        res = [1, 2.3, 3, 3, 5, 5, 8.4, 9]
        self.assertTrue(Solution().mergeKLists(nums, 3) == res)


if __name__ == "__main__":
    unittest.main()
```
