21. 合并两个有序链表【简单】【链表】【双指针】

4 篇文章 0 订阅
4 篇文章 0 订阅

题目

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 

示例 1:


输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]



示例 2:

输入:l1 = [], l2 = []
输出:[]



示例 3:

输入:l1 = [], l2 = [0]
输出:[0]
 


提示:

两个链表的节点数目范围是 [0, 50]
-100 <= Node.val <= 100
l1 和 l2 均按 非递减顺序 排列


示例图片


思路:

思路1. 转数组→排序→再转链表

思路2. 双指针


解法1:

1. 链表转数组

2. 对数组进行排序(注意:js中sort方法,负数时会出错,因为是按编码顺序排的)

3. 排序后的数组 转链表

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */

// List转数组 
var listToArr = function(list) {
    const arr = [];
    // 注意括号中的判断条件
    while(list !== null) {
        arr.push(list.val);
        list = list.next;
    }
    return arr;
} 

// 数组 转List
var arrToList = function(arr) {
    var head = new ListNode();
    var headCopy = null;
    arr.forEach(i => {
        var node = new ListNode();
        node.val = i;
        node.next = null;
        head.next = node;
        // 重要:动态更新head节点
        head = node;
        // 记住头节点,最后返回值时要用到
        if (headCopy === null) {
            headCopy = node;
        }
    })
    return headCopy;
}

/**
 * @param {ListNode} list1
 * @param {ListNode} list2
 * @return {ListNode}
 */
var mergeTwoLists = function(list1, list2) {
    // 1. list 转数组
    const arr1 = listToArr(list1);
    const arr2 = listToArr(list2);

    // 2. 对数组进行排序
    // 如果调用sort方法时没有使用参数,将按字母顺序对数组中的元素进行排序,
    // 说得更精确点,是按照字符编码的顺序进行排序。
    // 所以负数排序出错
    const arr = [...arr1, ...arr2].sort((a, b) => a - b);

    // 3. 数组 转list
    const list = arrToList(arr);
    return list;
};


解法2:双指针

关键点:(画图 + 过程中打印)

1. 健壮性判断

2. 使用copyHead保存初始头节点,后面返回值时要用到

3. p和q指向的节点同时有值时,才能进行比较

4. 前进时的两句关键代码 

5. 如果有一个指针指向空了,将另一个直接加到currentHead后面

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} list1
 * @param {ListNode} list2
 * @return {ListNode}
 */
var mergeTwoLists = function(list1, list2) {
    // 健壮性判断
    if(!list1){ return list2 };
    if(!list2){ return list1 };

    let p = list1;
    let q = list2;
    let currentHead = new ListNode();
    // 保存初始头节点,返回结果时要用到
    const copyHead = currentHead;
    // 两个指向的节点 都有值时,才能进行比较
    while(p !== null && q !== null) {
        if (p.val <= q.val) {
            // 将p指向的节点,加到currentHead尾巴上
            const node = new ListNode();
            node.val = p.val;
            currentHead.next = node;
            // 更新头结点
            currentHead = node;
            // 关键两句:list1指向它的后面一个节点
            list1 = list1.next;
            // 更新p的指向
            p = list1;
        } else {
            // 将q指向的节点,加到currentHead尾巴上
            const node = new ListNode();
            node.val = q.val;
            currentHead.next = node;
            // 更新头节点
            currentHead = node;
            // 关键两句:list2指向它的后面一个节点
            list2 = list2.next;
            // 更新q的指向
            q = list2;
        }
    }
    // 如果p指向null了,将q指向的节点及其后面的全部节点,添加到currentHead尾巴上
    if (p === null) {
        currentHead.next = q;
    }
    // 如果q指向了null了,将p指向的节点及其后面的全部节点,添加到currentHead尾巴上
    if(q === null) {
        currentHead.next = p;
    }
    return copyHead.next;
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值