「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」。
一、 题目
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例 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 = [[]] 输出:[]
二、 解析
链表的定义
首先,要实现链表,我们先搞懂一些链表的基本东西,因为这很重要!
链表是一组节点组成的集合,每个节点都使用一个对象的引用来指向它的后一个节点。指向另一节点的引用讲做链。下面我画了一个简单的链接结构图,方便大家理解。
-
- 节点中左侧储存val数据,右侧next储存下一个链表节点的引用地址
-
- 有上面的储备知识,我们总体的思路就是把链表转成数组,通过Array中的sort排序,然后再把数组转成Array
三、 解题
解题方法一: 用for循环的方法去拆链表->转数组->再组装成链表
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode[]} lists
* @return {ListNode}
*/
var mergeKLists = function(lists) {
let res = new ListNode() // 最后要返回的链表
let control = res
let arr = [] // 中间排序用的数组
// 1. 转数组
lists.forEach( (v,i) => {
while(1) {
if(v) {
arr[arr.length ] = v.val
v = v.next
} else {
break
}
}
})
// 2. 数组没数据就返回
if(arr.length === 0) return null
// 排序
arr.sort((a,b) => a-b)
// 3. 再组装成链表返回
arr.forEach((v,i) => {
control.next = new ListNode(v);
control = control.next;
})
return res.next
}
这种方法执行效率高
解题方法二:用递归的方法去拆链表->转数组->再组装成链表
/**
* @param {ListNode[]} lists
* @return {ListNode}
*/
var mergeKLists = function(lists) {
let arr = []
lists.forEach(v => flatArr(v,arr))
arr.sort((a,b) => a -b)
if(arr.length == 0) return null
let newListNode = new ListNode(arr[0])
arrToList(arr,newListNode)
return newListNode
}
var flatArr = function (listNode,arr) {
if(listNode) {
arr.push(listNode.val)
if(listNode.next) {
flatArr(listNode.next,arr)
}
}
}
var arrToList = function arrToList(arr,listNode) {
arr.forEach((v,i) => {
if(i != 0) {
let node = new ListNode(v)
mountedLastNode(listNode, node)
}
})
}
var mountedLastNode = function (listNode,lastNode) {
if(!listNode.next) {
listNode.next = lastNode
} else {
mountedLastNode(listNode.next,lastNode)
}
}
这个方法效率不高主要在于,最后把排好序的数组转成链表的时候,每次调mountedLastNode方法都去遍历了一次链表,重复了,但也是思路的一种,后期再优化下。
四、思考
虽然链表数据结构在实际开发业务中并不是太常用,但在react hooks源码中有用到,在一定的场景,链表的效率会比数组快,前端了解下这种数据结构还是必要的。