程序员面试宝典-遍历一次求出单链表的中间节点
遍历一次求出单链表的中间节点
题目
题目:给出一个单链表, 不知道节点N的值, 怎样只遍历一次就可以求出中间节点,写出算法。
第一眼的解法:
第一次看到题目,我们可以想到首先第一次遍历获取链表的长度,然后求出链表长度的一半,第二次进行遍历一半的长度,
获取中间节点。时间复杂度为O(n+0.5n),时间复杂度还好,但是我们进行了两次遍历操作。
双指针的解法:
我们采用两个指针,设立两个指针, 比如*p1和*p2。
p2每次移动两个位置, 即p2=p2-> next-> next,
p1每次移动一个位置, 即p1=p1-> next。
当p2到达最后一个节点时, p1就是中间节点了。
我们这里思路想到的话,是比较容易的 需要仔细考虑的地方是终止的地方。
我们简单使用奇数个节点和偶数个节点进行简单分析。
我们可以有两种思路来判断循环截止。
while (p2->next != NULL&&p2->next->next != NULL)
//p2节点的下个节点不为空 并且p2节点的下下个节点 不为空
//这种判断方式是提前判断的方式,最后的结果是符合我们的要求的。 满足条件才执行。
while ( p2 != NULL && p2->next!= NULL) //执行后判断 执行后判断 p2是否已经越界 延迟判断的方式
//具体采用什么方式 我们只要代入简单的例子进行模拟一下就可以
代码比较简单
node *searchmid(node *head) //查找单链表的中间结点
{
node *p, *q;
p = head;
q = head;
while (q->next != NULL&&q->next->next != NULL)//改动部分:保证q->next不为空 判断Next提前判断 执行前判断
{
q = q->next->next;
p = p->next;
}
return p;
}
//两种代码的结果 并不一致 延迟判断多执行的一次 所以如果是偶数个节点,中间节点会靠后一个节点。
//node *searchmid(node *head) //查找单链表的中间结点
//{
// node *p, *q;
// p = head;
// q = head;
// while (q != NULL && q->next != NULL)//延迟判断
// {
// q = q->next->next;
// p = p->next;
// }
// return p;
//}