前端算法(23)

36 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

题目

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

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

输入: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

题目解析

思路一

通过一次拿出两个数组元素,合并成一个新元素之后存放到新数组中,全部遍历后,再将新数组再次迭代,然后再通过数组元素判断, for循环中i每次加二,在最后时,数组长度如果为偶数,刚好有两个元素可以进行合并;如果为基数,判断i与长度大小,大于等于时说明为奇数,l2需要赋值为null。完成后继续迭代。

var mergeKLists = function(lists) {
    // 如为空数组直接返回
    if (!lists.length) return null;
    // 数组长度为一也可直接返回,这也是大多数情况的返回条件
    if (lists.length == 1) return lists[0];
    // newLists是新数组,迭代用
    let newLists = [], l2;
    for(let i = 0; i < lists.length; i = i + 2){
        let l1 = lists[i];
        // 判断长度是否为奇, 奇数则l2需赋值为null
        if(i < lists.length - 1){
            l2 = lists[i+1];
        }else {
            l2 = null;
        }
        // 新数组插入新元素
        newLists.push(mergeTwoLists(l1, l2));
    }
    // 迭代
    return mergeKLists(newLists);
};
//尾插法合并两个链表
function mergeTwoLists(l1, l2) {
    let head = new ListNode(), pre = head
    while (l1 && l2) {
        if (l1.val > l2.val) {
            pre.next = l2;
            l2 = l2.next;
        } else {
            pre.next = l1;
            l1 = l1.next;
        }
        pre = pre.next;
    }
    pre.next = l1 ? l1 : l2;
    return head.next;
};

思路二

暴力解法,将所有的链表节点数字加到数组里,然后利用数组排序,之后生成新的链表。

var mergeKLists = function(lists) {
    let nums = [];
    // 将所有的链表节点上的数都加到数组里
    for(let list of lists){
        while(list!=null){
            nums.push(list.val);
            list = list.next;
        }
    }
    // 排序
    nums.sort((a,b)=>a-b);
    // 生成新的链表
    const newNode = new ListNode(nums[0]);
    // 保存地址
    let root = newNode;
    // 循环数组,将每个数字加入新链表
    for(let i = 0;i<nums.length;++i){
        const node = new ListNode(nums[i]);
        // 加入链表末尾
        root.next = node;
        // 往后移
        root = root.next;
    }
    // 第一个节点是多余的,不需要
    return newNode.next;
};