【LeetCode】21.合并两个有序链表(简单)

【被OJ毒打的第七天】LeetCode_简单_21.合并两个有序链表

点此去做

题干:
    将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的
提示:
    输入和输出的链表元素皆为从小到大排列!
    struct ListNode {
        int val;
        ListNode *next;
        ListNode(int x) : val(x), next(NULL) {}
    };
输入:
    2->3->4, 1->2->5
输出:
    1->2->2->3->4->5

1.我的做法

执行用时:8~16ms,8.9MB

思想:在两个链表不为空时,持续遍历,遍历过程中比较当前位置两链表元素的大小,将小的一个添加到结果链表上,并让此链表和结果链表都前进一位

实现:首先考虑传入空链表的特殊情况(其实也不知道他到底有没有这个边缘用例);然后比较输入两链表头节点值的大小,用较小的那个值初始化 res;接着,需要拷贝一个链表 p 作为操作结果链表的指针(否则返回的 res 就只有最后一个节点);然后先对头结点值较小的链表做循环,循环结束后再对另一个链表做循环防止还有一些节点未被纳入 res

ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
    if (l1 == NULL) {
        return l2;
    }
    if (l2 == NULL) {
        return l1;
    }
    ListNode* fir;
    ListNode* sec;
    if (l1->val <= l2->val) {
        fir = l1;
        sec = l2;
    } else {
        fir = l2;
        sec = l1;
    }
    ListNode* res = new ListNode(fir->val);
    fir = fir->next;
    ListNode* p = res;
    while (fir != NULL) {
        if (sec != NULL && sec->val <= fir->val) {
            p->next = new ListNode(sec->val);
            p = p->next;
            sec = sec->next;
        } else {
            p->next = new ListNode(fir->val);
            p = p->next;        
            fir = fir->next;
        }
    }
    while (sec != NULL) {
        p->next = new ListNode(sec->val);
        p = p->next;
        sec = sec->next;
    }
    return res;
}

疑惑:由于原题目相当不清晰,我这段代码是带了一点之前的偏离思路的(分 fir 和 sec 实际上是不需要的);但是我重新修改过之后,执行时间反而变长了(12~28ms)...就很郁闷,我把改过的代码也贴在下面,个人猜测可能是由于:头节点值较小的链表中的值整体程度上也容易比另一个链表要小,所以先对其循环从数据上讲节省了时间(?)

ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
    if (l1 == NULL) {
        return l2;
    }
    if (l2 == NULL) {
        return l1;
    }
    ListNode* res;
    if (l1->val <= l2->val) {
        res = new ListNode(l1->val);
        l1 = l1->next;
    } else {
        res = new ListNode(l2->val);
        l2 = l2->next;
    }
    ListNode* p = res;
    while (l1 != NULL) {
        if (l2 != NULL && l2->val <= l1->val) {
            p->next = new ListNode(l2->val);
            p = p->next;
            l2 = l2->next;
        } else {
            p->next = new ListNode(l1->val);
            p = p->next;
            l1 = l1->next;
        }
    }
    while (l2 != NULL) {
        p->next = new ListNode(l2->val);
        p = p->next;
        l2 = l2->next;
    }
    return res;
}

2.进阶做法

执行用时:8~20ms,9MB(其实也没有很快,但是思路很棒)

思想:将当前位置较小的那个值定下来,指针后移,将剩余的两个链表部分再次递归合并

ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
    if(l1 == NULL) {
        return l2;
    }
    if(l2 == NULL) {
        return l1;
    }
    if(l1->val <= l2->val) {
        l1->next = mergeTwoLists(l1->next, l2);
        return l1;
    } else {
        l2->next = mergeTwoLists(l1, l2->next);
        return l2;
    }
}

现在发现其实 Top 2~3 的代码真正执行的时间也差不离,只是有时候突然会 0ms,4ms这样(也不知道为啥)

所以也不要过分追求执行速度啦!从多个角度思考题目,寻找巧妙的思路和完整的题解吧~

那么接下来就开始中等难度的挑战吧!

Fighting!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值