力扣876 - 链表的中间结点【快慢指针】

我就在中间反复横跳~

  • 一、题目描述
  • 二、思路分析
    • 在这里插入图片描述
  • 三、整体代码展示
  • 四、总结与提炼

一、题目描述

给定一个头结点为 head 的非空单链表,返回链表的中间结点。

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

示例 1:

输入:[1,2,3,4,5]
输出:此列表中的结点 3 (序列化形式:[3,4,5])
返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
注意,我们返回了一个 ListNode 类型的对象 ans,这样:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.

示例 2:

输入:[1,2,3,4,5,6]
输出:此列表中的结点 4 (序列化形式:[4,5,6])
由于该列表有两个中间结点,值分别为 3 和 4,我们返回第二个结点。

提示:

  • 给定链表的结点数介于 1 和 100 之间。

二、思路分析

好,看完题目的描述,我们来分析一下去求解这道题目

  • 从题目的描述来看很清晰,就是去求出一个链表的中间结点,我们知道,对于【单链表】而言,只能是通过头结点指针一一地遍历下去才能找到对应的结点,不像是数组那样支持随机访问,那这里也是一样,我们也是要去进行遍历,但是使用的不是一个指针,而是两个,这里我们俗称叫做【双指针】,我是用的是双指针中的一种,叫做【快慢指针】,很多力扣上链表方面的题目都会使用到双指针,而且使用这个【快慢指针】的也是很多,因此你需要掌握
  • 好,话不多说,我们来分析一下如何去求解这道题目,所谓快慢指针,也就是快指针走得快一些,通常上就是快指针走两步,慢指针走一步,首先来看看两个快慢指针初始化的样子,可以看到一开始均位于【head】头结点处。从这里我们可以知晓中间结点为【3
    力扣876 - 链表的中间结点【快慢指针】_第1张图片
  • 然后每次快指针走两步,慢指针走一步,没到结尾,继续走

力扣876 - 链表的中间结点【快慢指针】_第2张图片

  • 然后可以看到,此时慢指针其实已经走到我们需要寻找的中间结点位置,这个时候其实已经不需要在遍历了,结束即可
  • 但是结束的条件是什么呢?可以看到此时【fast->next == NULL】,这其实就是循环遍历结束的条件

力扣876 - 链表的中间结点【快慢指针】_第3张图片

  • 然后你是不是认为这样就可以了,我们提交一下看看。但是可以看到后台给出了报错,然后可以知晓结点的个数不一样了。我们使用这个例子再去做做看

力扣876 - 链表的中间结点【快慢指针】_第4张图片

  • 此时快慢指针走的距离还是不变:快指针走两步,慢指针走一步

力扣876 - 链表的中间结点【快慢指针】_第5张图片

力扣876 - 链表的中间结点【快慢指针】_第6张图片

  • 可以看到,此时【fast】指针遍历完毕,【slow】此时指向了4这个结点

力扣876 - 链表的中间结点【快慢指针】_第7张图片

  • 然后我们来看一下题目给出的要求:因为这里是两个中间结点,所以我们需要返回第二个,也就是【4
  • 那可以看出本题还有第二种需要考虑的场景就是偶数个结点的链表,那结束循环的条件是什么呢?可以看到此时【fast == NULL】,上面奇数个结点的时候是【fast->next == NULL】,因此这两个结束条件我们都需要写入循环中
  • 那它们怎么进行一个连接呢?你觉得是哪一种,没错,就是第一种,因为这两个情况只要满足一个就可以跳出进行【return】了,而且return的都是【slow】,
while(fast != NULL && fast->next != NULL)
while(fast != NULL || fast->next != NULL)

力扣876 - 链表的中间结点【快慢指针】_第8张图片

三、整体代码展示

题目代码很简单,以下是使用C++实现的

class Solution {
public:
    ListNode* middleNode(ListNode* head) {
        ListNode* fast, *slow ;
        fast = slow = head;
        /*
            fast->next != NULL —— 表示链表结点数为奇数
            fast != NULL —— 表示链表结点数为偶数
        */
        while(fast != NULL && fast->next != NULL)
        {
            //快指针每次都两步,慢指针每次走一步
            fast = fast->next->next;
            slow = slow->next;
        }
        return slow;
    }
};

四、总结与提炼

  • 最后我们来总结一下本文所介绍的内容,本文讲解的是一道力扣中有关求解链表中间结点的题目,从上面可以看出本题的代码并不复杂,但是要考虑到链表的个数时奇数还是偶数,然后需要在循环中加上一些限制条件,才能通过所有的测试案例
  • 所以大家在思考题目的时候要尽量考虑的周全一些,因为有公司在面试的时候给出的网站链接是不给测试用例的,这就需要我们自己去思考了,这个能力大家也是需要锻炼,才可以沉着冷静地去面试

以上就是本文所要描述的所有内容,感谢您对本文的观看,如有疑问请于评论区留言或者私信我都可以

你可能感兴趣的:(LeetCode算法笔记,链表,数据结构)