本文讲解找链表的中间节点的两种方法
目录
题目链接:链表的中间结点
法一:遍历链表法
遍历链表算出链表长度n,再遍历到n/2。就能求出中间节点,这种方法的时间复杂度为n+n/2 = 3n/2 -> O(n),且这种方法对于是空链表的情况也适用,故无需格外判断。
C++代码:
class Solution {
public:
ListNode* middleNode(ListNode* head) {
ListNode* cur = head;
int len = 0;
while (cur)
{
len++;
cur = cur->next;
}
cur = head;//重置
len /= 2;
while (len--) cur = cur->next;
return cur;
}
};
C代码:
struct ListNode* middleNode(struct ListNode* head)
{
//法一、遍历链表法
int len = 0;
struct ListNode* cur = head;
while (cur)
{
len++;
cur = cur->next;
}
cur = head;
for (int i = 0; i < len / 2; i++)
{
cur = cur->next;
}
return cur;//对于空链表也同样适用,直接返回NULL
}
法二、快慢指针法
fast(快指针)slow(慢指针),慢指针一次走一步,快指针一次走两步。
- 针对有偶数个结点的链表,fast走到尾节点算终止条件。
- 针对有奇数个结点的链表,fast走到NULL 算终止条件。
无论偶数还是奇数个结点的链表,slow最后指向的节点就是中间节点。
注:【快慢指针:本质上不说两个指针谁走的快,谁走的慢,而是指谁先走。先走多少步是可以自己设置的,本题就设置fast每次走2步,slow每次走1步。】
法二是更优算法,可以实现只遍历链表一次
C++代码:
class Solution {
public:
ListNode* middleNode(ListNode* head) {
ListNode* fast = head, *slow = head;//定义快慢指针
while (fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
};
C代码:
struct ListNode* middleNode(struct ListNode* head)
{
//法二、快慢指针法
struct ListNode* fast, * slow;
fast = slow = head;//初始条件,快慢指针均为头指针
while (fast && fast->next)//结束条件会因链表个数是奇偶个而判断条件不同
{
slow = slow->next;//慢指针每次走一步
fast = fast->next->next;//快指针每次走两步
}
return slow;
}