LeetCode 23. Merge k Sorted Lists(合并 k 个有序链表)

原题

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

题目:
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。

Example:

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

My Solution

方案一(超时)

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        res = head = ListNode(-1)
        output = []
        
        if not lists:
            return output
        if len(lists) == 1:
            return lists[0]

        mark_null = 0
        mark_continue_null = 0
        while mark_null < len(lists):

            min_count = None
            for sublist_index in range(len(lists)):

                if lists[sublist_index]:
                    mark_continue_null = 1
                    if min_count is None:
                        min_count = lists[sublist_index].val
                    if lists[sublist_index].val <= min_count:
                        min_count = lists[sublist_index].val
                        min_sublist_index = sublist_index
                else:
                    mark_null += 1
                    # mark_continue_null *= 1
            if min_count is None:
                return output
            res.next = ListNode(min_count)
            output.append(min_count)
            # res.next = None
            res = res.next
            mark_null = 0
            if mark_continue_null == 1:
                lists[min_sublist_index] = lists[min_sublist_index].next
            else:
                pass
        
        return head.next

方案二(超时)

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        if not lists:
            return []
        if len(lists) == 1:
            return lists[0]
        amount = len(lists)
        # interval = 1
        mark_null = 0
        # while mark_null < amount - 1:
        for i in range(1, amount):
            lists[0] = self.merge2Lists(lists[0], lists[i])
        return lists[0]
    def merge2Lists(self, l1, l2):
        head = point = ListNode(0)
        while l1 and l2:
            if l1.val <= l2.val:
                point.next = l1
                l1 = l1.next
            else:
                point.next = l2
                l2 = l2.next
            point = point.next
        if not l1:
            point.next = l2
        else:
            point.next = l1
        return head.next

Reference solution

思路分析:

思路一 :
这里是 k 个有序链表 ,小詹看到第一反应是直接递归使用前边合并两个有序链表的思路 ,对 ,完全没毛病的 。然后参考答案里是类似的 ,只不过合并的方式不一样 ,这里采取的是两两合并的方式 ,过程见下图 :
在这里插入图片描述

注:自己的方法就是合并效率太低,参考答案采用了两两合并,再下一轮两两合并,类似归并排序的思想,效率大幅提升。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        amount = len(lists)
        interval = 1
        while interval < amount:
            for i in range(0, amount - interval, interval * 2):
                lists[i] = self.merge2Lists(lists[i], lists[i + interval])
            interval *= 2
        return lists[0] if amount > 0 else lists
        
    def merge2Lists(self, l1, l2):
        head = point = ListNode(0)
        while l1 and l2:
            if l1.val <= l2.val:
                point.next = l1
                l1 = l1.next
            else:
                point.next = l2
                l2 = l2.next
            point = point.next
        if not l1:
            point.next = l2
        else:
            point.next = l1
        return head.next

这种方式的结果大概是 beat 65% 左右。

思路二:
还有一种看起来比较复杂的办法 ,但是结果却很赞 。大体思路分为三步 :

  • 创建一个列表

  • 将所有链表的元素值 append 进列表

  • 进行排序 ,之后再转换为链表结构

代码实现如下 :

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        # 创建一个列表
        self.nodes = []
        head = point = ListNode(0)
        # 将所有链表的节点元素append进列表
        for l in lists:
        	while l:
        		self.nodes.append(l.val)
        		l = l.next
        for x in sorted(self.nodes):
        	point.next = ListNode(x)
        	point = point.next
        return head.next

反思:

  1. 不同的归并方式效率差别极大,尽可能设计采用归并排序的思想,同步进行两两合并,不要range每轮只合并一次;
  2. 本题依旧是链表类问题,用python做模拟链表很不方便,还是转成C语言来写好了;
  3. 题目中明确说明:type lists: List[ListNode] :rtype: ListNode,即列表中的元素为ListNode类型;返回类型也必须为ListNode类型;自己总是尝试着直接用链表进行操作,答案没错,不过跟出题思路已经偏差了,还是改C语言好了。
  4. 注意要学会熟练运用高效的归并排序思想:
   amount = len(lists)
   interval = 1
   while interval < amount:
       for i in range(0, amount - interval, interval * 2):
           lists[i] = self.merge2Lists(lists[i], lists[i + interval])
       interval *= 2
   return lists[0] if amount > 0 else lists
        

猜你喜欢

转载自blog.csdn.net/Dby_freedom/article/details/82864143