题目如下:
这道题呢,这里我写出了两种解决办法,一种遍历链表来得出中间结点,一种通过快慢指针来得出中间结点
第一种:
遍历:
首先我们设置一个计数器count,来记录链表的长度,写一个函数来遍历链表,返回
count的一半的大小,即为这个链表的中间结点。(在代码的最前面,写一个typedef方便后续命名结构体)
typedef struct ListNode ListNode;
int lenl(ListNode* head)
{
ListNode* tail=head;
int count=0;
while(tail)
{
count++;
tail=tail->next;
}
return count/2;
}
我们获取了中间结点之后,我们只需要将头结点设置为这个中间结点就可以了
struct ListNode* middleNode(struct ListNode* head) {
int len=lenl(head);
while(len>0)
{
head=head->next;
len--;
}
return head;
}
这里我们重点需要知道的是,while 的循环条件,len>=0还是len>0
分析;
如果我们循环条件为len>=0
这里,以我们的示例一为例来解释
首先,我们的 len 通过计算得知为 2 ,如果len>=0的话,那么
第一次循环 len = 2进入循环
此时head向前,到达2的位置
第二次循环 len=1进入循环
此时head向前,到达3的位置
第三次循环 len=0 进入循环
此时head向前,到达4的位置
我们来验证一下:
一旦我将循环的结束条件写为len>=0那么就会导致头结点多向前走一步,所以我们这里应该为len>0,改正后,我们再来提交一下。
OK,这样就过辣!
第一种方法大家可能很容易想到,但是第二种方法用途非常广泛,使用其的地方也特别多——快慢指针
先来根据一个小学公式:a=2c;
如果这里a代表了链表的总长度,那么c就代表链表长度的一半
链表分为空链表,奇数链表,偶数链表
题目规定,本题没有空链表的出现,所以我们这里只讨论奇数和偶数链表。
首先我们来看奇数链表。
上图,我们分析一下:
当我们的fast指针走到链表的最后一个元素,我们的slow指针刚好落在我们的中间结点上,此时我们的fast就不能再向前了,因为我们的fast的next已经是空了,我们如果还要继续向前的话,就会造成解引用空指针的情况发生,进而导致程序报错。
偶数链表:
当我们的fast指针走到NULL的时候,我们的slow指针刚好落在我们的中间结点上,此时我们的fast就不能再向前了,因为我们的fast已经是空了,我们如果还要继续向前的话,就会造成解引用空指针的情况发生,进而导致程序报错。
下来我们具体的写一下代码:
struct ListNode* middleNode(struct ListNode* head) {
ListNode* slow=head;
ListNode* fast=head;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
}
return slow;
}
我们在这里需要注意的是,我们的循环条件一定是fast&&fast->next
原因:如果我们先判断fast->next,当链表是一个偶数链表的时候fast自身已经为空了,无法解引用,会导致程序报错,所以,我们这里应该首先判断fast为不为空,顺序不能交换。
本站资源均来自互联网,仅供研究学习,禁止违法使用和商用,产生法律纠纷本站概不负责!如果侵犯了您的权益请与我们联系!
转载请注明出处: 免费源码网-免费的源码资源网站 » Leetcode刷题
发表评论 取消回复