这是我参与11月更文挑战的14天,活动详情查看:2021最后一次更文挑战」。
前言
一直都计划学习数据结构与基本算法,但是平时都看一阵停一阵。现在决心坚持下去,我准备从LeetCode的HOT100开始,每天完成1~2道习题,希望通过这种方式养成持续学习的习惯。因为我是做iOS开发的,主要是用Objective-C语言,最近也在学习Swift,所以本系列的题解都将使用swift语言完成,本文更新的是LeetCode中HOT100的第14题023 合并K个升序链表。
题目
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例 1:
输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
1->4->5,
1->3->4,
2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6
示例 2:
输入:lists = []
输出:[]
示例 3:
输入:lists = [[]]
输出:[]
提示:
1. k == lists.length
2. 0 <= k <= 10^4
3. 0 <= lists[i].length <= 500
4. -10^4 <= lists[i][j] <= 10^4
5. lists[i] 按 升序 排列
6. lists[i].length 的总和不超过 10^4
分析
依次合并
本题是合并 k 个有序链表,我们在之前的文章中刚完成合成两个有序链表的问题 LeetCode之HOT100--021 合并两个有序链表,那么本题的题解就很简单,可以用合并两个有序链表的方法,将 k 个有序链表依次进行合并即可。
- 优点是空间复杂度只有O(1),时间复杂度为O(n)
创建链表法
我们的目的其实就是将 k 个链表中的所有元素进行排序形成一个新的链表。所以除了上述的依次合并法之外,我们还可以先将所有的元素保存到一个数组中,然后对该数组进行排序,最后将排序后的数组转换成链表结构即可。本题的题解就是使用这种方式完成的。
- 优点是思路很简单,时间复杂度在于排序的复杂度O(n*logn)
- 缺点是空间复杂度比较高,需要数组保存所有元素数据没并且所有节点要重新创建
题解
/**
* Definition for singly-linked list.
* public class ListNode {
* public var val: Int
* public var next: ListNode?
* public init() { self.val = 0; self.next = nil; }
* public init(_ val: Int) { self.val = val; self.next = nil; }
* public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; }
* }
*/
//扩展 ListNode,添加通过数组创建链表的方法
extension ListNode {
//通过数组创建链表的方法
func CreatList(_ Array: [Int]) -> ListNode? {
if let val = Array.first {
self.val = val
}else{
return nil
}
var cnt = Array.count - 1
while cnt > 0 {
let Node = ListNode(Array[cnt])
Node.next = self.next
self.next = Node
cnt -= 1
}
return self
}
}
class KLLC023 {
func mergeKLists(_ lists: [ListNode?]) -> ListNode? {
if lists.isEmpty {
return nil
}
//保存所有的元素
var result: [Int] = []
for list in lists {
var point = list
while point != nil {
result.append(point!.val)
point = point?.next
}
}
//将所有元素进行排序后 创建链表
return ListNode().CreatList(result.sorted())
}
}