刷题使我快乐,满脸开心.jpg
谢谢大家的支持!点个在看再走哟~
- 来源:力扣(LeetCode)
- 链接:https://leetcode.cn/problems/merge-k-sorted-lists/
- 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题目
给你一个链表数组,每个链表都已经按升序排列
。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例 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 = [[]]
输出:[]
提示:
k == lists.length
0 <= k <= 10^4
0 <= lists[i].length <= 500
-10^4 <= lists[i][j] <= 10^4
lists[i]
按升序
排列lists[i].length
的总和不超过10^4
思路
这道题虽然标的是困难,但是其实思路上是比较直接的,属于是对于数据结构和基础算法思维的应用的题目。
首先我们先来看基本的思路:
1、我们可能暂时还没有处理过合并k个链表,但是我们肯定很容易想象合并两个链表,那么只是把两个链表的对比横向扩展下:同时比较k个链表的头结点,加入结果链表
。当然,还有后续节点则需要再次重复这个过程,直到所有链表节点都加入为止。
这个思路没有问题,剩下的就是考虑降低时间复杂度
了。对于这种场景的话,比较推荐的就是堆排序
了。(刷题解会看到优先队列
的思路,其实是一个道理)
2、继续沿着合并两个链表的思路去想,把k个链表的合并拆分成一个又一个的两个链表合并
即可。同样的需要考虑时间复杂度的优化,那就是采用分治的方式
,两两合并,最终合并成为结果。
代码
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
// 分治方法
func mergeKLists(lists []*ListNode) *ListNode {
if len(lists) <= 0 {
return nil
}
return merge(lists, 0, len(lists)-1)
}
func merge(lists []*ListNode, left, right int) *ListNode {
if left == right {
return lists[left]
}
mid := (left + right) / 2
return mergeTwo(merge(lists, left, mid), merge(lists, mid + 1, right))
}
func mergeTwo(a, b *ListNode) *ListNode {
if a == nil {
return b
}
if b == nil {
return a
}
veryHead := &ListNode{}
head := veryHead
for a != nil || b != nil {
if a == nil {
head.Next = b
b = b.Next
} else if b == nil {
head.Next = a
a = a.Next
} else if a.Val > b.Val {
head.Next = b
b = b.Next
} else {
head.Next = a
a = a.Next
}
head = head.Next
}
return veryHead.Next
}
// 最小堆方法
func mergeKLists(lists []*ListNode) *ListNode {
h := hp{}
for _, head := range lists {
if head != nil {
h = append(h, head)
}
}
// 堆化
heap.Init(&h)
veryHead := &ListNode{}
now := veryHead
for len(h) > 0 {
// 初始化之后,堆顶为最小值
node := heap.Pop(&h).(*ListNode)
if node.Next != nil {
// 如果有下个节点,继续入堆,会自动调整,保持堆顶为最小
heap.Push(&h, node.Next)
}
now.Next = node
now = now.Next
}
return veryHead.Next
}
type hp []*ListNode
func (h hp) Len() int {
return len(h)
}
func (h hp) Less(i, j int) bool {
return h[i].Val < h[j].Val
}
func (h hp) Swap(i, j int) {
h[i], h[j] = h[j], h[i]
}
func (h *hp) Push(v interface{}) {
*h = append(*h, v.(*ListNode))
}
func (h *hp) Pop() interface{} {
a := *h
v := a[len(a)-1]
*h = a[:len(a)-1]
return v
}
看到这里了,点个赞点个在看呗!~ 多谢啦!~