每日一道算法面试题(20):leecode23 合并K个排序链表

1.算法题目

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

示例:

输入:
[
  1->4->5,
  1->3->4,
  2->6
]
输出: 1->1->2->3->4->4->5->6

2.算法思路

算法思路:

  1. 暴力法:每次遍历 n 个链表查找最小的值放入链表指定位置,算法复杂度是 O(kN),其中 N 是总共节点的数量;
  2. 分治法:两两比较临近的链表,第一轮比较过后合并成 k/2 个有序链表,第二轮比较后合并成 k/4 个有序链表,…;重复这一过程,直到剩余最后一个有序链表,即为符合题意的最终链表,算法复杂度 O(Nlogk)

3.算法代码

    public class ListNode {
        int val;
        ListNode next;
        ListNode(int x) { val = x; }
    }
    
    public ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0) {
            return null;
        }
        int len = lists.length;
        int step = 1;
        while (step < len) {
            for (int i = 0; i < len - step; i = i + 2*step) {
                lists[i] = mergeTwoLists(lists[i], lists[i + step]);
            }
            step *= 2;
        }
        return lists[0];
    }

    // 合并两个有序链表:算法复杂度 O(n),其中 n 为两个链表节点的总数量
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode prevHead = new ListNode(-1);
        ListNode prev = prevHead;
        while (l1 != null && l2 != null) {
            if (l1.val <= l2.val) {
                prev.next = l1;
                l1 = l1.next;
            } else {
                prev.next = l2;
                l2 = l2.next;
            }
            prev = prev.next;
        }
        prev.next = l1 != null ? l1 : l2;
        return prevHead.next;
    }

如果你有疑问或更好的算法思路,欢迎留言交流!!!

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页