1.判断单链表是否带环?若带环,求环的长度?求环的入口点?
(1)判断是否带环
Node* IfRing(Node* list)
{
Node* slow = list;
Node* fast = list;
while (fast&&fast->next)
{
slow = slow->next; //慢指针一次走一步
fast = fast->next->next;//快指针一次走两步
if (slow==fast)
{
return fast; //fast追上slow时返回快指针
}
}
return NULL; //表示fast->next为空,链表不带环
}
(2)求环的长度
求环的长度只需在第一次的相遇点开始,快慢指针继续走,当再次相遇时,走过的次数即使长度
int Length(Node* list)
{
Node* fast = IfRing(list);
if (fast)
{
Node* slow = fast;
int count = 0;
while (fast&&fast->next)
{
slow = slow->next;
fast = fast->next->next;
++count;
if (slow == fast)
{
return count;
}
}
return 0;
}
}
(3)求环的入口
Node* Entry(Node* list)
{
Node* fast = IfRing(list);//fast代表交点开始走
Node* cur = list;//cur从最开始的结点走
while (fast&&fast->next)
{
cur = cur->next;
fast = fast->next;
if (fast == cur) //相遇时代表走到了入口点
{
return fast;
}
}
return NULL;
}
2.判断两个链表是否相交,若相交,求交点。(假设链表不带环)
求两个链表的相交点:
代码
ListNode* IfCoverge(ListNode** list1, ListNode** list2)//返回值是环内相遇点 判断是否相交(链表不带环)
{
//让一个链表的尾指向另外一个链表的头,若有交点,则会形成环
if (*list1 == NULL)
return NULL;
if (*list2 == NULL)
return NULL;
ListNode* cur1 = *list1;
ListNode* cur2 = *list2;
while (cur1->_next)
{
cur1 = cur1->_next;
}
while (cur2->_next)
{
cur2 = cur2->_next;
}
if (*list1 == *list2)
return *list1;
else if (cur1 == cur2)
return cur1;
else
{
cur2->_next = *list1;
IfRing(*list2); //调用之前的判断是否带环的函数。返回值值快慢指针的相遇的点
}
}
ListNode* Coverge(ListNode* list1,ListNode* list2)//两个链表交点(可能也是环入口点)
{ //已知两个链表相交,则长的链表先走K步,K(size1-size2).之后两个链表同时走,相遇点就是交点
ListNode* cur1 = list1;
ListNode* cur2 = list2;
size_t size1 = Size(list1);
size_t size2 = Size(list2);
if (size1 > size2)
{
size_t k = size1 - size2;
while (k--)
{
cur1 = cur1->_next;
}
}
else
{
size_t k = size2 - size1;
while (k--)
{
cur2 = cur2->_next;
}
}
while (1)
{
if (cur1==cur2)
return cur1;
cur1 = cur1->_next;
cur2 = cur2->_next;
}
}
3 判断两个链表是否相交,若相交,求交点。(假设链表可能带环)【升级版】
1 两个链表都不带环
(1)没有交点 (2)有一个交点
2 一个链表带环,一个不带环
(3)没有交点
3 两个链表都带环
(4)没有交点 (5)有一个交点(交点有可能是入口点) (6)有两个交点
ListNode* Node(ListNode* list1, ListNode* list2)
{
ListNode* ret1 = Ret(list1);
ListNode* ret2 = Ret(list2);
if (!ret1&&!ret2) //1 -两个链表都不带环
{
ListNode* point = IfCoverge(&list1, &list2);
if (point == NULL)
{
return NULL; //1-1 没有交点
}
return Coverge(list1, list2); //1-2 一个交点
}
else if ((!ret1&&ret2) || (ret1&&!ret2)) //2 一个带环一个不带环
{
return NULL;
}
else // 3 两个都带环
{
//1-两个环不相交
//2-两个环的入口点相同
//3-两个环相交且有两个交点
if (ret1 == ret2) // 3--2 入口点相同
{
ret1->_next = NULL;
ret2->_next = NULL;
Coverge(list1, list2);
}
else
{
ListNode* tmp = ret1->_next;
while (tmp != ret1&&tmp != ret2)
{
tmp = tmp->_next;
}
if (tmp == ret1)
{
printf("两个链表分别带环,但不相交\n");
return NULL; //3-1 没有交点
}
printf("有两个交点\n"); //3-3 有两个交点
printf(" %d\n", ret1->_data);
return ret2;
}
}
}