1.判断单链表是否带环?若带环,求环的长度?求环的入口点?

int IsCycle(Node* p)
{
Node* slow, *fast;
fast = slow = p;
slow = slow->next;
fast = fast->next->next;
while ((fast != NULL) ||(fast->nest != NULL)) 
{
slow = slow->next;
fast = fast->next->next;
if (slow == fast)
{
return 1;       //  有环
}


}
return 0;               // 无环
}

---------------------------------------------------------------------------------------------------------------------------------------------------------------------


把上面返回的fast的值传给equal
int CycleLength (Node* equal)
{
Node* length = equal;
int count = 1;
length = length->next;
while (length != equal)
{
length = length->next;
count++;
}
return count;


}

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

链表面试进阶


如图所示 :假设 链表从开始到 环入口点的距离为a, 从环入口点到fast指针和slow指针相交的地方长度记做c, 环的长度记做b。


可以得到 : 2(a+c) = a+nb+c   2倍的慢指针等于快指针。所以 a+c = nb , a = nb-c;所以只要环上某点满足a = nb-c, 那它就是入口点。   




Node* Enter(Node* p, Node* meet)
{
assert(p);
assert(meet);
Node* cur1 = p;
Node* cur2 = meet;


while (cur1 != cur2)
{
cur1 = cur1->next;
cur2 = cur2->next;
if (cur1 == cur2)
{
return cur1;
}


}
assert(false);
return NULL;
}


2.判断两个链表是否相交,若相交,求交点。(假设链表不带环) 





Node* MeetNode(Node* p1, Node* p2)
{
assert(p1 && p2);
int len1, len2;
while (p1)
{
len1++;
p1 = p1->next;
}
while (p2)
{
len2++;
p2 = p2->next;
}
int longlist = p1;
int shortlist = p2;
if (len1 < len2)
{
longlist = p2;
shortlist = p1;


}
int gap = abs(len1 - len2);
while (gap--)
{
longlist = longlist->next;
}
while (longlist != shortlist)
{
longlist = longlist->next;
shotrlist = shortlist->next;
}
return longlist;


}

3.判断两个链表是否相交,若相交,求交点。(假设链表可能带环)【升级版】 

分情况讨论

链表面试进阶第一种情况 ,一条有环,一条无环。这种情况必不可能相交


两个指针,一个快一个慢,一起走。先走第一个链表:快慢指针永远不会相等。再走第二个指针:fast == slow 所有判断出一条链表有环一条链表无环,所以符合第一种情况则 无交点  return NULL;

链表面试进阶第二种情况,这种虽然有环,但是也没相交


同一样, fast 指针和slow指针一起走, 则会返回两个不同的 Node * meet  , 两个不同的相交点 , 则依旧不想交。

链表面试进阶 第三种情况 有环相交,可以套用上面的方法



先第一种方法:知道两个链表的头结点,用一个链表的头结点,将其转化为求一条循环链表的进入处,求得Node* meet处后再求Node*  Enter处。

让两个链表一起走,判断的条件是(PHead1->next != Enter) 和(PHead2->next != Enter)。 

然后比较两个链表走的步数,再让longlist走(longlist- shortlist)步,当longlist与shortlist相等时,返回longlist或者shortlist就是所求的交点。


链表面试进阶 两链共用一环


此时两个链表共用一个环,故其有两个入口点,随便选择一个输出就是其交点。两个入口点求解方法与上面的相同,fast与slow指针先求meetlist点,再根据结论2(a+c) = a+nb+c,就可求出交点。


分类:

技术点:

相关文章: