876. 链表的中间节点
解题思路:快慢指针法(双指针)
我们不能直接随机访问链表中间节点(不像数组可以通过下标定位),所以要使用遍历技巧。
最优方法是使用:快慢指针。
✨ 快慢指针技巧:
-
定义两个指针:
slow
每次走 1 步;fast
每次走 2 步;
-
当
fast
到达链表末尾时,slow
恰好指向链表的中间节点。
为什么这个方法有效?
- 快指针走得比慢指针快 1 倍;
- 所以当快指针走完链表时,慢指针只走了一半,正好指向中间。
代码实现
/*** 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* fast = head; // 快指针,每次走两步ListNode* low = head; // 慢指针,每次走一步// 快指针到达末尾时,慢指针刚好在中间while (fast != nullptr && fast->next != nullptr) {fast = fast->next->next;low = low->next;}return low;}
};
复杂度分析
项目 | 复杂度 |
---|---|
时间复杂度 | O(n) |
空间复杂度 | O(1) |
只遍历一次链表 | ✅ 高效 |
其中
n
是链表的长度。只使用了两个指针变量,空间非常节省。