本博客算法清单
1. 判断单链表是否有环
2. 求含环的单链表环的起始结点
3. 求环的长度
4. 判断两个链表是否相交
- 判断单链表是否有环
设置快慢指针,快指针一次走两步,慢指针一次走一步,若存在环,则两个指针必定在环中相交,且慢指针未绕环一圈,或者在环入口处相交
Node *IsCircle(List plist)
{
Node *quick = plist;
Node *slow = plist;
while (quick != NULL && quick->next != NULL)
{
quick = quick->next->next;
slow = slow->next;
if (quick == slow)
{
return quick;
}
}
return NULL;
}
- 求含环的单链表环的起始结点
方法一 数学计算
上图来源https://blog.csdn.net/bitboss/article/details/51648030
Node *findBegin(List plist)
{
Node *p = IsCircle(plist);
Node *q = plist;
if (p == NULL) return NULL;
while(p!=q)
{
p = p->next;
q = q->next;
}
return q;
}
方法二 截断环
步骤一:将快慢指针的相遇处断开,此时出现两个链表,并交于一点,
步骤二;分别求出两个链表的长度,长的为A,短的为B,使长的链表先走A-B的长度
步骤三:此时两个链表的长度相同,使两个链表同时走,每次走一步,
判断两个结点是否相同若相同则就是环入口结点
Node *FirstIntersection(List pa)
{
Node *p = IsCircle(pa);
Node *q = pa;
Node *s = p->next;
p->next = NULL;
if (p == NULL)
{
return NULL;
}
int len1 = GetLength(p);
int len2 = GetLength(q);
int gap = len1 - len2;
if (gap > 0)
{
for (int i = 0; i < gap; i++)
{
p = p->next;
}
}
else
{
for (int i = 0; i < -gap; i++)
{
q = q->next;
}
}
while (p != q)
{
p = p->next;
q = q->next;
}
return p;
}
- 求环的长度
求出快慢指针在环中的交点后,将再次设置快慢指针,快指针一次走两步,慢指针一次走一步,当两个指针再次相遇时,所走过的长度就是环的长度
int RingLen(List plist)
{
Node *quick = IsCircle(plist);
Node *slow = quick;
int count=0;
while (quick !=NULL && quick->next!=NULL)
{
quick = quick->next->next;
slow = slow->next;
count++;
if (quick == slow)
{
return count;
}
}
return count;
}
- 判断两个链表是否相交,求出第一个相交的节点;
可参考求含环的单链表环的起始结点方法
若A和B中有环,则采取将A和B中断开的方法,在最后连接
Node *FirstIntersection(List plist1,List plist2)
{
Node *p = IsCircle(plist1);
Node *q = IsCircle(plist2);
if((p==NULL&& q!=NULL) || (p!=NULL&&q==NULL))
{
return NULL;
}
if( p!=NULL )
{
Node *s = p->next; //断开plist1中的环
p->next = NULL;
}
q = IsCircle(plist2);//判断plist2的环和plist1是否相同
if(q != NULL) //不是同一个环,不相交
{
p->next = s;//还原plist1
return NULL;
}
//之前有环,现在两个链表都没有环
int len1 = GetLength(plist1);
int len2 = GetLength(plist2);
Node *p1 = plist1->next;
Node *p2 = plist2->next;
int gap = len1-len2;
if(gap > 0)
{
for(int i=0;i<gap;i++)
{
p1 = p1->next;
}
}
else
{
for(int i=0;i<-gap;i++)
{
p2 = p2->next;
}
}
while(p1 != NULL)
{
if(p1 == p2)
{
p->next = s;
return p1;
}
p1 = p1->next;
p2 = p2->next;
}
return NULL;
}