1.题目
https://leetcode.cn/problems/middle-of-the-linked-list/description/
给你单链表的头结点
head
,请你找出并返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。
示例 1:
输入:head = [1,2,3,4,5] 输出:[3,4,5] 解释:链表只有一个中间结点,值为 3 。示例 2:
输入:head = [1,2,3,4,5,6] 输出:[4,5,6] 解释:该链表有两个中间结点,值分别为 3 和 4 ,返回第二个结点。提示:
提供的代码模版
- 链表的结点数范围是
[1, 100]
1 <= Node.val <= 100
/** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */ struct ListNode* middleNode(struct ListNode* head) { }
2.自解
代码
两次遍历算法
struct ListNode* middleNode(struct ListNode* head)
{
struct ListNode* cur=head;
int sum_node=0;
//计算节点个数
while(cur)
{
sum_node++;
cur=cur->next;
}
sum_node/=2;
cur=head;
while(sum_node)
{
sum_node--;
cur=cur->next;
}
return cur;
}
执行结果
3.代码分析
先计算节点的总个数sum_node,再sum_node/=2;,最后执行sum_node次,返回节点
4.LeetCode官方解法
代码
C++
class Solution {
public:
ListNode* middleNode(ListNode* head) {
ListNode* slow = head;
ListNode* fast = head;
while (fast != NULL && fast->next != NULL) {
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
};
LeetCode没有提供C代码,转换为C代码后
struct ListNode* middleNode(struct ListNode* head)
{
struct ListNode* slow=head;
struct ListNode* fast=head;
while (fast != NULL && fast->next != NULL)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
分析
只需要一次遍历就能完成任务(快慢指针)
注意:慢指针slow一次走一个节点,快指针fast一次走两个节点,当节点为偶数时,最后一次循环时fast值为尾节点的next(fast为NULL,fast->next为NULL->next不合法);当节点为奇数时,最后一次循环时fast指向尾节点的val(fast不为NULL但fast->next为NULL)
综上,注意fast->next和fast不能有一个为空指针才能继续遍历