栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【经典算法题】合并K个有序链表

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【经典算法题】合并K个有序链表

【经典算法题】合并K个有序链表 Leetcode 0023 合并K个有序链表

问题描述

  • 问题链接:Leetcode 0023 合并K个有序链表

解法一

分析

  • 考点:归并排序

  • 类似于归并排序,如下图,这里使用自底向上归并排序,每一行代表当前还剩余多少链表没有被合并,当最终合并成一个链表时,就是答案。这里合并两个链表会用到:Leetcode 0021 合并两个有序链表。

代码

  • C++
// 自底向上归并排序
class Solution {
public:
    ListNode *merge(ListNode *l1, ListNode *l2) {
        if (l1 == NULL) return l2;
        if (l2 == NULL) return l1;
        
        if (l1->val < l2->val) {
            l1->next = merge(l1->next, l2);
            return l1;
        } else {
            l2->next = merge(l1, l2->next);
            return l2;
        }
    }

    ListNode *mergeKLists(vector &lists) {

        if (lists.empty()) return NULL;
        for (int step = 1; step < lists.size(); step += step)  // 每次合并的两个链表的索引差值
            for (int i = 0; i + step < lists.size(); i += step + step)  // i 代表两个待合并链表中的第一个
                lists[i] = merge(lists[i], lists[i + step]);
        return lists[0];
    }
};
  • Java
// 自底向上归并排序
class Solution {
    // 返回l1和l2合并后链表的头结点
    private ListNode mergeTwoList(ListNode l1, ListNode l2) {

        if (l1 == null) return l2;
        if (l2 == null) return l1;

        if (l1.val < l2.val) {
            l1.next = mergeTwoList(l1.next, l2);
            return l1;
        } else {
            l2.next = mergeTwoList(l1, l2.next);
            return l2;
        }
    }

    public ListNode mergeKLists(ListNode[] lists) {

        if (lists == null || lists.length == 0) return null;
        for (int step = 1; step < lists.length; step += step)  // 每次合并的两个链表的索引差值
            for (int i = 0; i + step < lists.length; i += (step + step))  // i 代表两个待合并链表中的第一个
                lists[i] = mergeTwoList(lists[i], lists[i + step]);  // list[i] 和 list[i+step] 进行合并
        return lists[0];
    }
}
  • Python
class Solution:
    def mergeKLists(self, lists: List[ListNode]) -> ListNode:
        if not lists:
            return None
        step = 1
        while step < len(lists):
            i = 0
            while i + step < len(lists):
                lists[i] = self.merge(lists[i], lists[i + step])
                i += step + step
            step += step
        return lists[0]

    def merge(self, l1, l2):
        if not l1:
            return l2
        if not l2:
            return l1
        if l1.val < l2.val:
            l1.next = self.merge(l1.next, l2)
            return l1
        else:
            l2.next = self.merge(l1, l2.next)
            return l2

时空复杂度分析

  • 时间复杂度: O ( n × l o g ( n ) ) O(n times log(n)) O(n×log(n)),n为所有链表个数。

  • 空间复杂度: O ( m ) O(m) O(m),m为链表个数。

解法二

分析

  • 考点:堆(优先队列)

  • 使用小顶堆,每次取出堆顶元素,此时一定是最小的元素,放到结果链表中,直到堆为空。这里的难点关键是如何实现堆中放入链表?(其实放入的只是链表的头指针),请参考代码的具体实现。

代码

  • C++
// 堆
class Solution {
public:
    struct Cmp {
        // STL容器在比较的时候用的是结构体的小括号运算符
        bool operator() (ListNode *a, ListNode *b) {
            return a->val > b->val;
        }
    };

    ListNode *mergeKLists(vector &lists) {

        priority_queue, Cmp> heap;  // 小顶堆
        auto dummy = new ListNode(-1), tail = dummy;
        for (auto l : lists) if (l) heap.push(l);

        while (heap.size()) {
            auto t = heap.top();
            heap.pop();
            tail = tail->next = t;
            if (t->next) heap.push(t->next);
        }
        return dummy->next;
    }
};
  • Java
// 堆
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {

        Queue heap = new PriorityQueue<>((v1, v2) -> v1.val - v2.val);
        ListNode dummy = new ListNode(-1), tail = dummy;
        for (ListNode l : lists)
            if (l != null)
                heap.add(l);
        
        while (!heap.isEmpty()) {
            ListNode t = heap.remove();
            tail = tail.next = t;
            if (t.next != null) heap.add(t.next);
        }
        return dummy.next;
    }
}

时空复杂度分析

  • 时间复杂度: O ( n × l o g ( n ) ) O(n times log(n)) O(n×log(n)),n为所有链表个数。

  • 空间复杂度: O ( m ) O(m) O(m),m为链表个数。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/591428.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号