Leetcode刷题笔记之链表篇876. 链表的中间结点

Posted 大家好我叫张同学

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode刷题笔记之链表篇876. 链表的中间结点相关的知识,希望对你有一定的参考价值。

😈博客主页:🐼大家好我叫张同学🐼
💖 欢迎点赞 👍 收藏 💗留言 📝 欢迎讨论! 👀
🎵本文由 【大家好我叫张同学】 原创,首发于 CSDN 🌟🌟🌟
精品专栏(不定时更新) 【数据结构+算法】 【做题笔记】【C语言编程学习】
☀️ 精品文章推荐
【C语言进阶学习笔记】三、字符串函数详解(1)(爆肝吐血整理,建议收藏!!!)
【C语言基础学习笔记】+【C语言进阶学习笔记】总结篇(坚持才有收获!)


前言

为什么要写刷题笔记
写博客的过程也是对自己刷题过程的梳理总结,是一种耗时有效的方法。
当自己分享的博客帮助到他人时,又会给自己带来额外的快乐和幸福。
(刷题的快乐+博客的快乐,简直是奖励翻倍,快乐翻倍有木有QAQ🙈)

题目内容

给定一个头结点为 head 的非空单链表,返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。

遍历求长法

要得到中间结点,我们很容易想到的一种方法就是:先遍历一遍链表,求出链表长度,然后再从头开始,走到中间结点去,返回中间结点。

算法图解

函数实现
struct ListNode* middleNode(struct ListNode* head)
    if(head == NULL || head->next == NULL)
      return head;
    int length = 0;
    struct ListNode* cur = head;
    while(cur)
        length++;
        cur = cur->next;
    
    cur = head;//cur再次返回头节点
    int step = length/2;//步数等于链表长度的一半
    while(step--)
        cur = cur->next;
    
    return cur;


虽然我们成功的写出来代码,也通过了测试。但是上面的代码并不是完美的代码!一份完美的代码应该是“简洁易读高效的”。而上面的这个代码并不简洁,存在着冗余的代码。下面我们就来仔细分析一下,提高自己编写代码的能力!

题目的提示中说了结点数介于1-100之间,那么我们就没必要考虑空链表这种情况了(这里仅从刷题的角度出发,符合题目要求即可)。
其次,当链表结点数量为1的时候,我们所写的函数主体部分如下:

    cur = head;
    int step = length/2;//length=1时,step = 0;
    while(step--) //条件为假,不进入循环内部
        cur = cur->next;
    
    return cur;//直接返回头节点

也就是结点为1时,也会返回头节点,不需要额外判断这种场景。
综上所述,那么我们原本代码所写的以下部分,可以完全删除:

    if(head == NULL || head->next == NULL)
      return head;
代码优化
struct ListNode* middleNode(struct ListNode* head)
    int length = 0;
    struct ListNode* cur = head;
    while(cur)
        length++;
        cur = cur->next;
    
    cur = head;//cur再次返回头节点
    int step = length/2;//步数等于链表长度的一半
    while(step--)
        cur = cur->next;
    
    return cur;


快慢指针法

跟链表相关的题目经常会涉及到快慢指针的方法,顾名思义,就是用两个指针,一个指针走的快,一个指针走得慢。

比如说这个题目,我们可以用快慢指针的方法来解决,快指针一次走两步慢指针一次走一步,当快指针结束的时候,慢指针停留的位置就是中间结点的位置。

算法图解

当结点为单数


结点为双数

通过画图分析我们可以知道,fast结束的条件是fast为最后一个结点,或者fast为空
此外,还可验证链表为空和仅有一个结点时也符合上述过程。(也就是说这种场景不需要单独进行判断处理)

函数实现
struct ListNode* middleNode(struct ListNode* head)
    struct ListNode *fast = head,*slow = head;
    while(fast && fast->next)
        fast = fast->next->next;//快指针一次走两步
        slow = slow->next;//慢指针一次走一步
    
    return slow;//慢指针指向第二个中间结点

注意while循环判断部分写的是循环继续的条件
虽然我们可能思考的是循环终止的条件,但是要转化为循环继续的条件。

以上是关于Leetcode刷题笔记之链表篇876. 链表的中间结点的主要内容,如果未能解决你的问题,请参考以下文章

Leetcode刷题笔记之链表篇剑指 Offer 18. 删除链表的节点

Leetcode刷题笔记之链表篇234. 回文链表

Leetcode刷题笔记之链表篇141. 环形链表

Leetcode刷题笔记之链表篇160. 相交链表

Leetcode刷题笔记之链表篇160. 相交链表

Leetcode刷题笔记之链表篇234. 回文链表