题目如下:
解题过程如下:
思路1:求单链表的结点总数,除2求中间结点的位置,返回中间位置的结点。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
typedef struct ListNode ListNode;
struct ListNode* middleNode(struct ListNode* head) {
//计算单链表的结点总数
ListNode* pcur = head;
int count = 0;
while (pcur)
{
count++;
pcur = pcur->next;
}
//除2得到中间结点的位置,返回中间位置结点
pcur = head;
int newCount = count / 2;
while (newCount)
{
pcur = pcur->next;
newCount--;
}
return pcur;
}
时间复杂度:O(n)
下面思路2的快慢指针法才是重中之重!!!
思路2:快慢指针,慢指针每次走一步,快指针每次走两步。
那么是&&
还是||
呢?
假设是||
,示例1为例子,fast != NULL
、fast->next == NULL
,有一个为真,进入循环,这不符合上述的分析结果,所以是&&
。
思考下列写法可不可行?
不行,若fast == NULL
,从左往右执行,fast ->next
就是对空指针的解引用。
完整代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
typedef struct ListNode ListNode;
struct ListNode* middleNode(struct ListNode* head) {
//建立快慢指针,慢指针每次走一步,快指针每次走两步
ListNode* slow, *fast;
slow = fast = head;
while (fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
时间复杂度:O(n)