力扣题目学习笔记(OC + Swift)23. 合并 K 个升序链表

23. 合并 K 个升序链表

给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。

方法一:顺序合并

记得前面实现过的两个升序链表的合并,我们能否利用之前实现的两个有序链表的合并呢?当然可以,但是性价比不高而已。

顺序合并执行流程
时间复杂度:假设每个链表长度为n,当i=0,ans长度为n,i=1时ans长度为2n,因此当i时ans长度为in,求和公式得到O(k+1)k/2n),约等于O(NK^2)
空间复杂度:O(1)

时间复杂度太高了,但是先实现再优化吧…

Swift

//朴素解法,利用之前已经实现的两个有序链表的合并算法
    func mergeKLists(_ lists: [ListNode?]) -> ListNode? {
   
        let cnt = lists.count
        guard cnt > 0 else {
   return nil}
     
        //合并两个有序链表函数
        func mergeTwoListNode(_ list1: ListNode?, _ list2:ListNode?) -> ListNode? {
   
            guard list1 != nil else {
    return list2 }
            guard list2 != nil else {
    return list1 }
            
            //构造哑巴节点
            let dummyNode = ListNode(-1);
            var pre:ListNode? = dummyNode;
            
            var list1 = list1
            var list2 = list2
            while list1 != nil && list2 != nil {
   
                if list1!.value < list2!.value {
   
                    pre?.next = list1!;
                    list1 = list1?.next;
                }else {
   
                    pre?.next = list2
                    list2 = list2?.next
                }
                pre = pre?.next
            }
            
            pre?.next = list1 != nil ? list1 : list2
            
            return dummyNode.next
        }
        
        
        
        var ans:ListNode?
        for i in 0..<cnt {
   
            ans = mergeTwoListNode(ans, lists[i])
        }
        
        return ans
    }

OC

- (ListNodeOC * _Nullable) mergeKLists:(NSArray <ListNodeOC *>*)lists {
   
    if (lists.count <= 0) {
   
        return nil;
    }
    
    ListNodeOC *ans = nil;
    for (NSInteger i=0; i<lists.count; i++) {
   
        ans = [self mergeTwoList:ans list2:lists[i]];
    }
    return ans;
}

- (ListNodeOC * _Nullable)mergeTwoList:(ListNodeOC * _Nullable)list list2:(ListNodeOC * _Nullable)list2 {
   
    if (!list || !list2) {
   
        return list ? list : list2;
    }
    
    //构造哑巴节点
    ListNodeOC *dummyNode = [[ListNodeOC alloc] initWithVal:-1];
    ListNodeOC *prev = dummyNode;
    while (list && list2) {
   
        if (list.val < list2.val) {
   
            prev.next = list;
            list = list.next;
        }else {
   
            prev.next = list2;
            list2 = list2.next;
        }
        
        prev = prev.next;
    }
    
    //将任意一个剩余的部分拼接起来
    prev.next = list ? list : list2;
    
    return dummyNode.next;
}

方法二、分治法 (推荐)

思路
考虑优化方法一,用分治的方法进行合并。

  • 将 k 个链表配对并将同一对中的链表合并;
  • 第一轮合并以后, k个链表被合并成了 k/2个链表,平均长度为 2n/k,然后是 k/4个链表, k/8个链表等等;
  • 重复这一过程,直到我们得到了最终的有序链表。

分治法程序执行流程
时间复杂度:渐进时间复杂度为 O(kn×log⁡k)
空间复杂度:O(logk)

Swift

//分治合并
    func mergeKLists(_ lists: [ListNode?]) -> ListNode? {
   
        
        func merge(_ lists: [ListNode?], _ left: Int, _ right:Int) -> ListNode? {
   
            if left == right {
   
                return lists[left]
            }
            
            if left > right {
    return nil }
            
            let mid = (left + right) >> 1
            //mergeTwoListNode 同方法一中
            return mergeTwoListNode(merge(lists, left, mid), merge(lists, mid+1, right))
        }
        
        return merge(lists, 0, lists.count-1)
    }

OC

- (ListNodeOC * _Nullable) merge:(NSArray <ListNodeOC *>*)lists left:(NSInteger)left right:(NSInteger)right {
   
    if (left == right) {
   
        return lists[left];
    }
    
    if (left > right) {
   
        return nil;
    }
    
    NSInteger mid = (left+right) / 2;
    //mergeTwoList 方法用上面👆🏻
    return [self mergeTwoList:[self merge:lists left:left right:mid] list2:[self merge:lists left:mid+1 right:right]];
}

//分治合并
- (ListNodeOC * _Nullable) mergeKLists:(NSArray <ListNodeOC *>*)lists {
   
    return [self merge:lists left:0 right:lists.count-1];
}

相关推荐

  1. 23. 合并 K 升序 - (LeetCode)

    2023-12-27 15:36:02       40 阅读
  2. 23. 合并k升序

    2023-12-27 15:36:02       30 阅读
  3. 刷题练习】23. 合并 K 升序

    2023-12-27 15:36:02       67 阅读
  4. 合并k升序

    2023-12-27 15:36:02       28 阅读
  5. LeetCode-23. 合并 K 升序

    2023-12-27 15:36:02       43 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-27 15:36:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-27 15:36:02       100 阅读
  3. 在Django里面运行非项目文件

    2023-12-27 15:36:02       82 阅读
  4. Python语言-面向对象

    2023-12-27 15:36:02       91 阅读

热门阅读

  1. SQL面试题挑战08:补全缺失日的月销售累计

    2023-12-27 15:36:02       61 阅读
  2. 初识k8s

    初识k8s

    2023-12-27 15:36:02      57 阅读
  3. Adobe Application Manager丢失或损坏 - 解决方案

    2023-12-27 15:36:02       117 阅读
  4. 四种NAT的网络结构

    2023-12-27 15:36:02       55 阅读
  5. electron DownloadItem如何从指定Url中下载文件

    2023-12-27 15:36:02       53 阅读
  6. 软件测试面试题——如果保证测试用例覆盖率

    2023-12-27 15:36:02       54 阅读