Leetcode 876. 链表的中间结点

477 阅读2分钟

原题链接: 876. 链表的中间结点 - 力扣(Leetcode)

tag: 双指针, 链表.

一. 题目

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

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

二. 题解

对于本题采用 双指针 的方法, 定义慢指针 slow 指向链表的头节点 head, 定义快指针 fast 指向链表的头节点 head. 慢指针 slow 一次走一步, 快指针 fast 一次走两步.

  • 对于 链表有奇数个节点 的情况, 当快指针 fast 指向链表的尾节点时候, 慢指针 slow 指向的节点即为链表的中间节点.

image.png

定义慢指针 slow, 快指针 fast.

ListNode* slow = head, * fast = head;

image.png

慢指针走一步.

slow = slow->next;

快指针走两步.

fast = fast->next->next;

image.png

重复这一步骤.

image.png

fast->next == nullptr 循环终止.

此时慢指针 slow 指向的节点即为链表的中间节点.

image.png

  • 对于链表有偶数个节点的情况, 当快指针 fast 指向链表尾节点后的空节点的时候, 慢指针 slow 指向的节点即为链表的中间节点(此时链表有两个中间节点, 返回第二个中间节点).

image.png

定义慢指针 slow, 快指针 fast.

ListNode* slow = head, * fast = head;

image.png

慢指针走一步.

slow = slow->next;

快指针走两步.

fast = fast->next->next;

image.png

重复这一步骤.

image.png

重复这一步骤.

image.png

fast->next == nullptr 循环终止.

此时慢指针 slow 指向的节点即为链表的中间节点.

image.png

返回链表的中间节点.

return slow;

三. 复杂度分析

时间复杂度: O(N), 其中 N 是链表的长度.

空间复杂度: O(1), 只需要常数空间存放 slowfast 两个指针变量.

四. 代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* middleNode(ListNode* head) {
        ListNode* slow = head, * fast = head;    // 定义慢指针 slow, 快指针 fast
        while (fast && fast->next) {
            slow = slow->next;    // 慢指针走一步
            fast = fast->next->next;    // 快指针走两步
        }
        return slow;    // 返回链表的中间节点
    }
};