链表的面试题3找出中间节点
来来来,接着继续我们的第三道题 。
解法
暴力求解
快慢指针
https://leetcode.cn/problems/middle-of-the-linked-list/submissions/
这道题的话,思路是非常明确的,就是让你找出我们这个所谓的中间节点并且输出。
那这道题我们就需要注意一些细节上的问题,或者说是对于整个链表结构的访问的理解要到位。
如果这道题放在顺序表上,那我们很容易就能根据下标来判断是否为中间节点。但是,问题就出在,链表是不能依据数组下标来访问的,那这道题我们很简单的思路就是,先得出链表长度,再定义变量值来求中间节点。那我把代码贴在下面。
暴力求解
typedef struct ListNode ListNode;
struct ListNode* middleNode(struct ListNode* head){ListNode* pcur = head;int count = 0;int ret=0;// 求链表的长度countwhile (pcur) {count++;pcur = pcur->next;}pcur=head;//重置pcur为头节点while(pcur&&ret<(count/2)){ret++;pcur=pcur->next;}return pcur;
}
快慢指针
那这道题应该放在第一道题的,因为这是非常好的一道题能看出我们的双指针法到底有多便捷。我们根据前两道题目也知道,双指针又叫快慢指针法,注定有一个指针走的快,有一个走得慢,我们根据走的快的指针和慢指针的差值的逻辑关系,来确定此时慢指针到底处于什么位置。
下面给大家放一张图表示一下快慢指针
从图中我们就能很容易的看到fast永远比slow快一步。这样做的好处是什么?我们在刚刚的暴力求解的时候,是不是要注意一个细节,那就是,我们的简单粗暴的代码,并不能同时涵盖奇数和偶数,需要分类讨论。而快慢指针就没有这样的麻烦,可以极大的缩短我们的时间复杂度,提高效率。
struct ListNode* middleNode(struct ListNode* head){struct ListNode *fast = head, *slow = head;while(fast && fast->next){slow = slow->next;fast = fast ->next ->next;}return slow;
}