原题链接: 876. 链表的中间结点 - 力扣(Leetcode)
tag: 双指针, 链表.
一. 题目
给你单链表的头结点 head
, 请你找出并返回链表的中间结点.
如果有两个中间结点, 则返回第二个中间结点.
二. 题解
对于本题采用 双指针 的方法, 定义慢指针 slow
指向链表的头节点 head
, 定义快指针 fast
指向链表的头节点 head
. 慢指针 slow
一次走一步, 快指针 fast
一次走两步.
- 对于 链表有奇数个节点 的情况, 当快指针
fast
指向链表的尾节点时候, 慢指针slow
指向的节点即为链表的中间节点.
定义慢指针 slow, 快指针 fast.
ListNode* slow = head, * fast = head;
慢指针走一步.
slow = slow->next;
快指针走两步.
fast = fast->next->next;
重复这一步骤.
fast->next == nullptr
循环终止.
此时慢指针 slow
指向的节点即为链表的中间节点.
- 对于链表有偶数个节点的情况, 当快指针
fast
指向链表尾节点后的空节点的时候, 慢指针slow
指向的节点即为链表的中间节点(此时链表有两个中间节点, 返回第二个中间节点).
定义慢指针 slow, 快指针 fast.
ListNode* slow = head, * fast = head;
慢指针走一步.
slow = slow->next;
快指针走两步.
fast = fast->next->next;
重复这一步骤.
重复这一步骤.
fast->next == nullptr
循环终止.
此时慢指针 slow
指向的节点即为链表的中间节点.
返回链表的中间节点.
return slow;
三. 复杂度分析
时间复杂度: O(N), 其中 N 是链表的长度.
空间复杂度: O(1), 只需要常数空间存放 slow
和 fast
两个指针变量.
四. 代码
/**
* 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; // 返回链表的中间节点
}
};