• LeetCode每日一练 —— 21. 合并两个有序链表


    🌟 前言

    Wassup guys!我是Edison 😎

    今天是 LeetCode 上的 leetcode 21. 合并两个有序链表

    Let’s get it!

    在这里插入图片描述



    1. 题目分析

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

    示例 1:
    在这里插入图片描述

    示例 2:
    在这里插入图片描述

    示例 3:
    在这里插入图片描述

    2. 题目图解

    这道题其实就是 归并 思路,每次取小的节点 尾插 到新链表

    🍑 思路一

    定义指针 list 1 指向第一个链表的 头节点,定义指针 list 2 指向第二个链表的 头节点

    再定义一个新链表,此时头节点 head 和 尾节点 tail 都为 NULL,如图所示👇
    在这里插入图片描述

    我们分析一下 尾插 的过程:

    1 次,当 list 1 等于 list 2 时,就把 list 1 插入到新链表中,给 headtail
    在这里插入图片描述

    2 次,当 list 2 小于 list 1 时,就把 list 2 插入到新链表中,更新 tail
    在这里插入图片描述

    3 次,当 list 1 小于 list 2 时,就把 list 1 插入到新链表中,更新 tail
    在这里插入图片描述

    这里直接看动图演示👇
    在这里插入图片描述

    注意:

    当其中任意一个链表指向 NULL 时,把剩余的链表的元素直接 拷贝 到新链表中。
     
    比如,list 1 先指向 NULL,那么直接把 list 2 剩余的元素拿到 新链表 中,也不用再更新 tail 了,直接返回新链表的 头节点

    为什么不更新 tail 呢?

    我们要返回的是 头节点 ,又不用返回新的 尾节点,这里定义的 tail 只是方便进行 尾插

    接口代码

    struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
        if (list1 == NULL) {
            return list2;
        }
        if (list2 == NULL) {
            return list1;
        }
        struct ListNode* head = NULL, *tail = NULL;
        while (list1 && list2) {
        	// list1 小于 list2
            if ((list1->val) < (list2->val)) {
                if (tail == NULL) {
                    head = tail = list1;
                }
                else {
                    tail->next = list1;
                    tail = list1;
                    // tail = tail->next
                }
                list1 = list1->next;
            }
            // list1 大于等于 list2
            else {
                if (tail == NULL) {
                    head = tail = list2;
                }
                else {
                    tail->next = list2;
                    tail = list2;
                    // tail = tail->next
                }
                list2 = list2->next;
            }
        }
        if (list1) {
            tail->next = list1;
        }
        if (list2) {
            tail->next = list2;
        }
        return head;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    提交结果
    在这里插入图片描述

    🍑 思路一

    我们可以新建一个 带头节点 的新链表,也就是 哨兵位 的头节点,这个节点不存储有效数据。

    那么这个 带头不带头 的区别在哪里呢?

    思路一 中,我们定义的新链表是不带头的,headtail 都指向 NULL,所以在插入时,要进行判断,tail 是否为 NULL 的情况。
     
    那么如果我设置一个 哨兵位 的头节点,那么根本不需要判断,哪怕此时一个值都没有,headtail 都不可能为 ,所以在进行 尾插 时,直接把元素插入到 哨兵位 后面即可。

    原理还是和 思路一 是一样的,所以直接看动图👇
    在这里插入图片描述

    注意:

    返回的时候,不能返回 head,而是返回 head 指向的 next,也就是 哨兵位 的下一个节点;
     
    因为题目给的两个链表是不带哨兵位的,所以我们合并以后,返回的也是不带哨兵位的

    接口代码

    // 带头节点的单链表
    struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
        struct ListNode* head = NULL, *tail = NULL;
    
        // 设置一个哨兵位
        head = tail = (struct ListNode*)malloc(sizeof(struct ListNode));
        head->next = NULL;
    
        while (list1  && list2) {
            if ((list1->val) < (list2->val)) {
                tail->next = list1;
                tail = list1;
                list1 = list1->next;
            }
            else {
                tail->next = list2;
                tail = list2;
                list2 = list2->next;
            }
        }
        if (list1) {
            tail->next = list1;
        }
        if (list2) {
            tail->next = list2;
        }
    
        // 释放
        struct ListNode* list = head->next;
        free(head);
        return list;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    提交结果
    在这里插入图片描述

  • 相关阅读:
    Spring学习笔记4 Bean的作用域
    java spring cloud 工程企业管理软件-综合型项目管理软件-工程系统源码
    0025【Edabit ★☆☆☆☆☆】【足球得分】Football Points
    什么是单元测试(unit testing)
    Android12之报错fatal error: ‘mediadrm/ICrypto.h‘ file not found
    JVM第七讲:JVM 基础 - Java 内存模型详解
    SVN安装教程
    python调用C语言库
    力扣设计循环队列
    爆肝整理 JVM 十大模块知识点总结,不信你还不懂
  • 原文地址:https://blog.csdn.net/m0_63325890/article/details/125986671