【每日一题Day293】LC23合并K个升序链表 | K指针 堆排序 归并排序

简介: 【每日一题Day293】LC23合并K个升序链表 | K指针 堆排序 归并排序

合并K个升序链表【LC23】

给你一个链表数组,每个链表都已经按升序排列

请你将所有链表合并到一个升序链表中,返回合并后的链表。

K指针
  • 思路:
    每次选择链表数组中的最小值,直至所有节点均为空
  • 实现
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        ListNode dummyNode = new ListNode(-1);
        ListNode cur = dummyNode;     
        while (true){
            int index = -1; 
            int min = Integer.MAX_VALUE;
            for(int i = 0; i < lists.length; i++){
                if (lists[i] != null && lists[i].val < min){
                    index = i;
                    min = lists[i].val;
                }
            }
            if (index == -1){
                break;
            }
            cur.next = lists[index];
            cur = cur.next;
            lists[index] = lists[index].next;
        }
        return dummyNode.next;
    }
}

复杂度

时间复杂度:O ( n k ) ,K为数组的长度,n为链表的平均长度

空间复杂度:O ( 1 )

堆排序
  • 思路:
    使用小顶堆存放K个节点,每次弹出最小的节点
  • 实现
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        ListNode dummyNode = new ListNode(-1);
        ListNode cur = dummyNode;     
        Queue<ListNode> pq = new PriorityQueue<>((v1, v2) -> v1.val - v2.val);
        for (ListNode node :lists){
            if (node != null){
                pq.offer(node);
            }
        }
        while (!pq.isEmpty()){
            ListNode min = pq.poll();
            if (min.next != null){
                pq.add(min.next);
            }
            cur.next = min;
            cur = cur.next;    
        }
        return dummyNode.next;
    }
}

复杂度


时间复杂度:O ( n l o g k ),K为数组的长度,n为链表的平均长度


空间复杂度:O ( k )

归并排序
  • 思路:
    对 K 条链表进行两两合并
  • 递归实现
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if (lists.length == 0) {
            return null;
        }
        int k = lists.length;
        while (k > 1) {
            int idx = 0;
            for (int i = 0; i < k; i += 2) {
                if (i == k - 1) {
                    lists[idx++] = lists[i];
                } else {
                    lists[idx++] = merge2Lists(lists[i], lists[i + 1]);
                }
            }
            k = idx;
        }
        return lists[0];
    }
    private ListNode merge2Lists(ListNode l1, ListNode l2) {
        if (l1 == null) {
            return l2;
        }
        if (l2 == null) {
            return l1;
        }
        if (l1.val < l2.val) {
            l1.next = merge2Lists(l1.next, l2);
            return l1;
        }
        l2.next = merge2Lists(l1, l2.next);
        return l2;
    }
}
作者:Sweetiee 🍬
链接:https://leetcode.cn/problems/merge-k-sorted-lists/solutions/220518/4-chong-fang-fa-xiang-jie-bi-xu-miao-dong-by-sweet/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

复杂度

时间复杂度:O ( n l o g k ) ,K为数组的长度,n为链表的平均长度

空间复杂度:O ( )

迭代实现

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if (lists.length == 0) {
            return null;
        }
        return merge(lists, 0, lists.length - 1);
    }
    private ListNode merge(ListNode[] lists, int lo, int hi) {
        if (lo == hi) {
            return lists[lo];
        }
        int mid = lo + (hi - lo) / 2;
        ListNode l1 = merge(lists, lo, mid);
        ListNode l2 = merge(lists, mid + 1, hi);
        return merge2Lists(l1, l2);
    }
    private ListNode merge2Lists(ListNode l1, ListNode l2) {
        ListNode dummyHead = new ListNode(0);
        ListNode tail = dummyHead;
        while (l1 != null && l2 != null) {
            if (l1.val < l2.val) {
                tail.next = l1;
                l1 = l1.next;
            } else {
                tail.next = l2;
                l2 = l2.next;
            }
            tail = tail.next;
        }
        tail.next = l1 == null? l2: l1;
        return dummyHead.next;
    }
}
作者:Sweetiee 🍬
链接:https://leetcode.cn/problems/merge-k-sorted-lists/solutions/220518/4-chong-fang-fa-xiang-jie-bi-xu-miao-dong-by-sweet/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

复杂度


时间复杂度:O ( n l o g k ),K为数组的长度,n为链表的平均长度


空间复杂度:O ( 1 )

目录
相关文章
|
4月前
|
存储 C语言
用指针处理链表
用指针处理链表
39 3
|
1月前
|
算法
LeetCode第23题合并 K 个升序链表
这篇文章介绍了LeetCode第23题"合并K个升序链表"的解题方法,使用分而治之的思想,通过递归合并链表的方式解决了这个难题。
LeetCode第23题合并 K 个升序链表
|
2月前
【数据结构OJ题】复制带随机指针的链表
力扣题目——复制带随机指针的链表
45 1
【数据结构OJ题】复制带随机指针的链表
|
1月前
|
存储 Python
【Leetcode刷题Python】23. 合并K个升序链表
合并K个升序链表的方法:使用数组排序的暴力求解法、使用小顶堆的高效方法,以及分而治之的策略,并提供了相应的Python实现代码。
13 1
|
1月前
|
Python
【Leetcode刷题Python】138. 复制带随机指针的链表
LeetCode上题目“138. 复制带随机指针的链表”的Python解决方案,包括两种方法:一种是在每个节点后复制一个新节点然后再分离出来形成新链表;另一种是构建一个字典来跟踪原始节点与其副本之间的映射关系,从而处理新链表的构建。
14 1
|
28天前
|
存储 算法 数据处理
指针与链表
指针与链表
49 0
|
1月前
|
存储 算法 Python
【面试题】合井K个升序链表
【面试题】合井K个升序链表
24 0
|
3月前
|
存储 人工智能 测试技术
每日练习之排序——链表的合并;完全背包—— 兑换零钱
每日练习之排序——链表的合并;完全背包—— 兑换零钱
24 2
|
3月前
23.合并K个升序链表
23.合并K个升序链表
|
3月前
|
算法
【经典LeetCode算法题目专栏分类】【第7期】快慢指针与链表
【经典LeetCode算法题目专栏分类】【第7期】快慢指针与链表