题目描述:
1.给定一个单链表,请设计程序判断该链表是否有环?
分析:我们知道单链表中一个节点只存在一个后继结点,所以若存在环形结构肯定是以下右图情况
因此,我们选择追逐法,选择一个指针p和一个指针q,每次q移动两个位置,p移动一个位置,如果单链表存在环形结构,那么最终p,q总会相遇在某处,,如果链表无环,则q将会率先为NULL。
参考代码如下:
typedef struct node* Node;
struct node
{
int val;
node *next;
};
//way1
bool isCircleList(Node head)
{
Node p=head,q=head;
while(p->next!=nullptr&&q->next!=nullptr)
{
p=p->next;
q=q->next->next;
if(p==q&&p!=nullptr)
return true;
if(q==nullptr&&p!=nullptr)
return false;
}
}
//way2
bool isCircleList(Node head)
{
Node p=head,q=head;
while(q!=nullptr&&q->next!=nullptr)
{
p=p->next;
q=q->next->next;
if(p==q)
break;
}
if(p==q&&p!=nullptr)
return true;
return false;
}
2.如果发现一个单链表有环,如何找到环的起始位置?
分析:这里就通过一系列的公式推导得出,链表起点到环的起点的长度与快慢指针相遇点到环的起始位置的长度相同来进行算法设计。在快慢指针相遇后,将快指针重新指向链表头部,同时让快指针q的速度和慢指针p的速度相同,继续移动两个指针,每次移动一步,当两个指针相遇时,就是链表环的起始位置。
代码如下:
Node getOrigPosCircleList(Node head)
{
Node p,q;
p=q=head;
while(q!=nullptr&&q->next!=nullptr)
{
p=p->next;
q=q->next->next;
if(p==q)
break;
}
if(p==q&&q!=nullptr&&q->next!=nullptr)
{
q=head;
while(q!=p)
{
p=p->next;
q=q->next;
}
return q;
}
else
return nullptr;
}