• 【C语言刷题】合并两个有序链表&反转链表


    活动地址:CSDN21天学习挑战赛

    Leetcode21——合并两个有序链表

    题目描述

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

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

    image.png

    示例 2:
    **输入:**l1 = [ ], l2 = [ ] 输出:[ ]

    示例 3:
    **输入:**l1 = [ ], l2 = [0] 输出:[0]

    提示:

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

    核心代码模式

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     struct ListNode *next;
     * };
     */
    
    
    struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
    {
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    思路分析和代码实现(C语言)

    思路其实很简单,这里用了哨兵结点作为新链表的头结点,用两个指针把两个链表中的结点互相比较,小的先尾插到新链表中,总会有一条链表先插完,没插完的链表把剩下的结点一次尾插到新链表。有一些要注意的点,首先创建了哨兵结点,定义了guard指针指向哨兵结点,这时应该立即给哨兵结点的next指针初始化为NULL,不然有野指针的潜在风险。定义两个指针cur1和cur2分别对应list1链表和list2链表,while循环的条件应当是cur1&&cur2,为什么呢?这样的话只要有一个链表先插完就立马跳出循环。在循环结束后要根据哪个链表还没插完,把剩余结点全部尾插到新链表。我们这里使用的辅助结点——哨兵结点是题目没提供的,我们应当在最后将其释放,不过释放前得先把哨兵结点的next指针的内容取出来,作为头指针返回。

    image.png
    代码实现

    struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
    {
        struct ListNode* cur1 = list1;
        struct ListNode* cur2 = list2;
        struct ListNode* guard = (struct ListNode*)malloc(sizeof(struct ListNode));
        guard->next = NULL;
        struct ListNode* tail = guard;
        
        while(cur1 && cur2)
        {
            if(cur1->val > cur2->val)
            {
                tail->next = cur2;
                tail = tail->next;
                cur2 = cur2->next;
            }
            else
            {
                tail->next = cur1;
                tail = tail->next;
                cur1 = cur1->next;
            }
        }
    
        if(cur1)
            tail->next = cur1;
        if(cur2)
            tail->next = cur2;
    
        struct ListNode* head = guard->next;
        free(guard);
        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

    Leetcode206——反转链表

    题目描述

    给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

    链接Leetcode206

    示例

    示例 1:
    **输入:**head = [1,2,3,4,5] 输出:[5,4,3,2,1]

    image.png

    示例 2:
    **输入:**head = [1,2] 输出:[2,1]

    image.png

    示例 3:
    **输入:**head = [] 输出:[]

    提示:

    • 链表中节点的数目范围是 [0, 5000]
    • -5000 <= Node.val <= 5000

    核心代码模式

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     struct ListNode *next;
     * };
     */
    
    
    struct ListNode* reverseList(struct ListNode* head)
    {
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    思路分析与代码实现(C语言)

    1.新链表头插法

    实际上有一道题和这个基本一样,只是要求的是使用数组,而这里使用的是单链表。思路也是可以借鉴互通的,不妨创建一个新的链表,不过相比于数组,这里不需要开辟新结点,只是把结点间的指向关系进行修改。定义一个新的头指针newHead,定义一个查找当前结点的cur指针,查找下一结点的next指针,只要cur不指向NULL,就把cur指向的结点放到新链表去,怎么放呢?把newHead的内容给cur指向结点的next指针,让它指向newHead原来指向的东西,再把cur指向结点的地址给newHead,让newHead指向该结点,不过要注意在执行这些操作之前要先把cur->next的值放到next去,在执行完后要把next的值再放到cur去。其实也就是让原来的结点从前向后一个一个头插到新链表中。
    image.png
    代码实现

    struct ListNode* reverseList(struct ListNode* head)
    {
        struct ListNode* cur = head;
        struct ListNode* newHead = NULL;
    
        while(cur)
        {
            struct ListNode* next = cur->next;
            cur->next = newHead;
            newHead = cur;
            cur = next;
        }
    
        return newHead;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2.三指针逆置法

    有没有想过这样一种方法,既然链表是通过指针联系的,那把指针指向关系逆转了不就能实现反转了吗,用三个指针,分别指向前一结点、当前结点和下一结点(prev、cur、next),只要cur指向不为NULL,就说还有结点没有反转,就把前一结点的地址赋给cur指向的当前结点的next指针,让它指向前一结点,然后三个指针都向后移动一位,不断循环至cur指向NULL。反转后的新链表的头结点由prev指向,返回prev即可。
    image.png
    代码实现

    struct ListNode* reverseList(struct ListNode* head)
    {
        struct ListNode* prev = NULL;
        struct ListNode* cur = head;
        struct ListNode* next = NULL;
    
        while(cur)
        {
            next = cur->next;
            cur->next = prev;
            prev = cur;
            cur = next;
        }
        return prev;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述

  • 相关阅读:
    第2章 MyBatis的核心配置
    wsl创建证书让chrome浏览器识别
    golang中的正则表达式使用注意事项与技巧
    基于低代码开发平台搭建的生产制造管理系统
    2022.8.8考试摄像师老马(photographer)题解
    (微信小程序系列:一)携带参数跳转半屏微信小程序 先 A->B 后 B ->A
    Gin+Xterm.js实现远程Kubernetes Pod(一)
    Three.js-绘制矩形shader
    基于JAVA科技专业师生沟通平台计算机毕业设计源码+系统+mysql数据库+lw文档+部署
    CodeCraft-21 and Codeforces Round 711 (Div. 2)A-F
  • 原文地址:https://blog.csdn.net/weixin_61561736/article/details/126283021