每日一算法题-合并链表

81 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

一、题目

image.png

struct ListNode {
    int val;
    ListNode *next = nullptr;
    inline ListNode(int x, ListNode* next = nullptr) : val(x), next(next) { }
};

ListNode* mergeList(ListNode* pHead1, ListNode* pHead2) {
    //---------
}

int main(int, char**)
{
    ListNode p1(1);
    ListNode p2(3);
    ListNode p3(5);
    p1.next = &p2;
    p2.next = &p3;
    p3.next = nullptr;

    ListNode p4(2);
    ListNode p5(4);
    ListNode p6(6);
    p4.next = &p5;
    p5.next = &p6;
    p6.next = nullptr;

    ListNode* pHead = mergeList(&p1, &p4);
    ListNode* cur = pHead;
    while(cur){
        cout << cur->val << endl;
        cur = cur->next;
    }

    return 0;
}

二、分析

根据题意,如果要将两个链表进行合并,只需要对两个链表先进行拆分,然后不断对子节点进行基本的链表插入动作就能实现
而在此基础上还想要将两个链表按照顺序合并,只需要对拆分的子节点进行比较,获取最小的合适的节点就行插入动作即可达到目的,这里题意给的两个链表本就是顺序链表,所以对两个联系表的第一个节点的比较就肯定是最小的合适的节点

三、模拟

  1. 先声明一个暂时的头结点

ListNode pHead(0);
ListNode* cur = &pHead;

  1. 对两个链表进行比较

if(pHead1->val < pHead2->val) 合适的节点就是pHead1;
else 合适的节点就是pHead2;

  1. 插入动作 cur->next = 合适的节点;
    cur = 合适的节点;\

4.迭代

合适的节点 指向它的 next节点;

四、实现

ListNode* mergeList(ListNode* pHead1, ListNode* pHead2) {
    ListNode pHead(0);
    ListNode* cur = &pHead;

    while(pHead1 && pHead2){
        if(pHead1->val < pHead2->val){
            cur->next = pHead1;
            pHead1 = pHead1->next;
        }else{
            cur->next = pHead2;
            pHead2 = pHead2->next;
        }
        cur = cur->next;
    }
    if(pHead1){
        cur->next = pHead1;
    }else {
        cur->next = pHead2;
    }
    return pHead.next;
}

因为这里的pHead是暂时的头结点,真正的头结点应该是pHead1和pHead2之间产出,所以在最后应该返回暂时的头结点指向的下一个节点。

五、结言

这道题不难,关键点在于需要保持顺序合并,这就用到排序的概念