反转链表、链表的中间结点、合并两个有序链表【LeetCode刷题日志】

这篇具有很好参考价值的文章主要介绍了反转链表、链表的中间结点、合并两个有序链表【LeetCode刷题日志】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

 一、反转链表

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

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

反转链表、链表的中间结点、合并两个有序链表【LeetCode刷题日志】,网络,c语言,算法,数据结构,笔记,c++

思路一:翻转单链表指针方向

这里解释一下三个指针的作用:

n1:记录上一个节点,如果是第一个就指向空

n2:记录此节点的位置

n3:记录下一个节点的位置,让翻转后能找到下一个节点,防止丢失指针的地址

/*
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* reverseList(struct ListNode* head) {
    if(head == NULL)
    {
        return NULL;
    }
    //初始条件
    struct ListNode* n1 = NULL,*n2 = head,*n3 = n2->next;
    //结束条件
    while(n2)
    {
        //迭代过程
        n2->next = n1;

        n1 = n2;
        n2 = n3;
        if(n3)
        n3 = n3->next;
        
    }
    return n1;
}

反转链表、链表的中间结点、合并两个有序链表【LeetCode刷题日志】,网络,c语言,算法,数据结构,笔记,c++

思路二:头插法

取原链表节点头插到新链表

/*
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
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;
}

反转链表、链表的中间结点、合并两个有序链表【LeetCode刷题日志】,网络,c语言,算法,数据结构,笔记,c++

二、链表的中间结点

给你单链表的头结点 head ,请你找出并返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

反转链表、链表的中间结点、合并两个有序链表【LeetCode刷题日志】,网络,c语言,算法,数据结构,笔记,c++

思路一:单指针法

  • 时间复杂度:O(N*1.5),其中 N 是给定链表的结点数目。

  • 空间复杂度:O(1),只需要常数空间存放变量和指针。

我们可以对链表进行两次遍历。第一次遍历时,我们统计链表中的元素个数 N;第二次遍历时,我们遍历到第 N/2 个元素(链表的首节点为第 0 个元素)时,将该元素返回即可。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* middleNode(struct ListNode* head) {
    int n = 0;
    struct ListNode*cur = head;
    while(cur != NULL)
    {
        ++n;
        cur = cur->next;
    }
    int k = 0;
    cur = head;
    while(k < n/2)
    {
        ++k;
        cur = cur->next;
    }
    return cur;
}

思路二:快慢指针法

  • 时间复杂度:O(N),其中 N 是给定链表的结点数目。

  • 空间复杂度:O(1),只需要常数空间存放 slow 和 fast 两个指针。

反转链表、链表的中间结点、合并两个有序链表【LeetCode刷题日志】,网络,c语言,算法,数据结构,笔记,c++

我们可以优化思路一,用两个指针 slow 与 fast 一起遍历链表。slow 一次走一步,fast 一次走两步。那么当 fast 到达链表的末尾时,slow 必然位于中间。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* middleNode(struct ListNode* head) {
    struct ListNode* slow = head,*fast = head;
    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
    }
    return slow;
}

三、合并两个有序链表

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

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

反转链表、链表的中间结点、合并两个有序链表【LeetCode刷题日志】,网络,c语言,算法,数据结构,笔记,c++

思路一(迭代法):

定义一个头指针和一个尾指针,从小到大依次尾插,直到一个链表为空时结束

反转链表、链表的中间结点、合并两个有序链表【LeetCode刷题日志】,网络,c语言,算法,数据结构,笔记,c++

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2) {
    if(l1 == NULL)    
    return l2;
    if(l2 == NULL)
    return l1;
    struct ListNode* head = NULL, *tail = NULL;
    while(l1 != NULL && l2 != NULL)
    {
        if(l1->val < l2->val)
        {
            //尾插
            if(tail == NULL)
            {
                head = tail = l1;
            }
            else{
                tail->next = l1;
                tail = tail->next;
            }
            l1 = l1->next;
        }
        else{
            if(tail == NULL)
            {
                head = tail = l2;
            }
            else{
                tail->next = l2;
                tail = tail->next;
            }
            l2 = l2->next;
        }
    }
    if(l1)
        tail->next= l1;
    if(l2)
        tail->next= l2;
    return head;
}

优化一:

先确定头结点,然后再循环判断val大小,尾插

struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2) {
    if(l1 == NULL)    
    return l2;
    if(l2 == NULL)
    return l1;
    struct ListNode* head = NULL, *tail = NULL;
    //先确定头节点
    if(l1->val < l2->val)
    {
        head = tail =l1;
        l1 = l1->next;
    }else{
        head = tail =l2;
        l2 = l2->next;
    }

    while(l1 && l2)
    {
            //尾插
        if(l1->val < l2->val)
        {   
            tail->next = l1;
            l1 = l1->next;
        }
        else{
            tail->next = l2;
            l2 = l2->next;
            }
    tail = tail->next;
    }
    if(l1)
        tail->next= l1;
    if(l2)
        tail->next= l2;
    return head;
}

优化二:

设置一个哨兵位的头节点,然后再去尾插。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2) {
    if(l1 == NULL)    
    return l2;
    if(l2 == NULL)
    return l1;
    struct ListNode* head = NULL, *tail = NULL;
    //哨兵位的头节点
    head = tail = (struct ListNode*)malloc(sizeof(struct ListNode));
    while(l1 && l2)
    {
            //尾插
        if(l1->val < l2->val)
        {   
            tail->next = l1;
            l1 = l1->next;
        }
        else{
            tail->next = l2;
            l2 = l2->next;
            }
    tail = tail->next;
    }
    if(l1)
        tail->next= l1;
    if(l2)
        tail->next= l2;
    struct ListNode* first = head->next;
    free(head);
    return first;
}

思路二(递归法):

(这是题解中大佬的一个解法)以迭代的思路写递归,尤为惊人!!!

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
    /*if判断:
    1.如果l1为空,返回l2
    2.如果l2为空,返回l1
    3.如果l1的值小于l2,比较l1的next值和l2,并把值赋给l1的下一个;返回l1
    4.反之,比较l1和l2的next值,并把值赋给l2的下一个;返回l2
    */
    if (l1 == NULL) {
            return l2;
        } else if (l2 == NULL) {
            return l1;
        } else if (l1->val < l2->val) {
            l1->next = mergeTwoLists(l1->next, l2);
            return l1;
        } else {
            l2->next = mergeTwoLists(l1, l2->next);
            return l2;
        }
}

反转链表、链表的中间结点、合并两个有序链表【LeetCode刷题日志】,网络,c语言,算法,数据结构,笔记,c++

因为有缓冲区的存在,C语言在操作文件的时候,需要做刷新缓冲区或者在文件操作结束的时候关闭文件。
如果不做,可能导致读写文件的问题。

今天就先到这了!!!

反转链表、链表的中间结点、合并两个有序链表【LeetCode刷题日志】,网络,c语言,算法,数据结构,笔记,c++

看到这里了还不给博主扣个:
⛳️ 点赞☀️收藏 ⭐️ 关注!

你们的点赞就是博主更新最大的动力!
有问题可以评论或者私信!!!文章来源地址https://www.toymoban.com/news/detail-772294.html

到了这里,关于反转链表、链表的中间结点、合并两个有序链表【LeetCode刷题日志】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 链表中的倒数第k个结点 合并两个链表 分割链表 链表的回文结构

    🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨ 🐻推荐专栏: 🍔🍟🌯C语言进阶 🔑个人信条: 🌵知行合一 🍉本篇简介::分析力扣中有关链表的部分题目. 题目来源于:牛客网-题目链接 输入一个链表,输出该链表中倒数第k个结点。 示例: 输入:1,{1,2,3,4,5} 返回值:{5} 创建两个指针: ①

    2024年02月10日
    浏览(41)
  • 第21关:基于链表的两个递增有序序列的合并

    任务描述 本关任务:给定两个递增的整数序列A和B,利用链表表示序列A和B,将A和B合并为一个递增的有序序列C,序列C不允许有重复的数据。要求空间复杂度为O(1)。 编程要求 输入 多组数据,每组数据有三行,第一行为序列A和B的长度n和m,第二行为序列A的n个元素,第三行为

    2024年02月05日
    浏览(57)
  • Leetcode 21. 合并两个有序链表

    题目链接:https://leetcode.cn/problems/merge-two-sorted-lists/description/ 两个链表都是升序链表,新建一个链表,引入伪头节点作为辅助节点,将各节点添加到伪节点之后,再用一个cur节点指向新链表的末尾 遍历两个链表,对比每个节点值,将更小的链表节点加入到新链表中 如果其中一

    2024年02月13日
    浏览(46)
  • LeetCode21.合并两个有序链表

    将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 : 输入:l1 = [1,2,4], l2 = [1,3,4] 输出:[1,1,2,3,4,4] 创建一个新的链表头节点(dummyNode)和一个指针current,用于表示当前节点。 在一个while循环中,比较两个链表的节

    2024年02月20日
    浏览(41)
  • LeetCode 21.合并两个有序链表

    题目链接 👉 LeetCode 21.合并两个有序链表👈 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 取小的进行尾插 👇 图解 👇 取小的进行尾插 👇 图解 👇 🥰 希望烙铁们能够理解欧! 总结🥰 以上就是本题讲解的全部内

    2024年02月13日
    浏览(50)
  • 【链表OJ】链表中倒数第k个结点 合并两个链表(含哨兵位) 分割链表 链表的回文结构

    前言: 💥🎈个人主页:​​​​​​Dream_Chaser~ 🎈💥 ✨✨刷题专栏:http://t.csdn.cn/UlvTc ⛳⛳本篇内容:力扣和牛客上链表OJ题目 目录  一、链表中倒数第k个结点 题目描述: 解题思路: 二.合并两个链表(含哨兵位)  题目描述: 解题思路:                                     

    2024年02月12日
    浏览(50)
  • Leetcode算法递归类—合并两个有序链表

    目录 21. 合并两个有序链表 题解: 代码: 将两个升序链表合并为一个新的  升序  链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。  示例 1: 示例 2: 示例 3: 提示: 两个链表的节点数目范围是  [0, 50] -100 = Node.val = 100 l1  和  l2  均按  非递减顺序  

    2024年02月13日
    浏览(39)
  • 合并两个有序链表,将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

    题记: 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1: 输入 :l1 = [1,2,4], l2 = [1,3,4] 输出 :[1,1,2,3,4,4] 示例 2: 输入 :l1 = [], l2 = [] 输出 :[] 示例 3: 输入 :l1 = [], l2 = [0] 输出 :[0] 提示: 两个链表的节点数

    2024年02月07日
    浏览(63)
  • 【Leetcode】反转链表 合并链表 相交链表 链表的回文结构

      目录 一.【Leetcode206】反转链表 1.链接 2.题目再现  3.解法A:三指针法 二.【Leetcode21】合并两个有序链表 1.链接 2.题目再现  3.三指针尾插法 三.【Leetcode160】相交链表 1.链接 2.题目再现 3.解法 四.链表的回文结构 1.链接 2.题目再现  3.解法 1.链接 反转链表 2.题目再现  3.解法

    2024年02月02日
    浏览(49)
  • 【代码随想录 | Leetcode | 第六天】链表 | 反转链表 | 两两交换链表中的节点 | 删除链表的倒数第 N 个结点

    欢迎来到小K的Leetcode|代码随想录|专题化专栏,今天将为大家带来反转链表、两两交换链表中的节点和删除链表的倒数第N个节点的分享 ✨ ✨题目链接点这里 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。 示例 1: 示例 2: 示例 3: 提示: 链表中节点的数

    2024年02月16日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包