两个链表是否相交

判断单链表中是否有环,找到环的入口节点:在MeetingNode方法中,当快慢指针(slow、fast)相遇时,slow指针肯定没有遍历完链表,而fast指针已经在环内循环了n(n>=1)圈。假设slow指针走了s步,则fast指针走了2s步。同时,fast指针的步数还等于s加上在环上多转的n圈,设环长为r,则满足如下关系表达式:

            2s = s + nr;

所以可知:s = nr;

假设链表的头节点到“环的尾节点“的长度为L(注意,L不一定是链表长度),环的入口节点与相遇点的距离为x,链表的头节点到环入口的距离为a,则满足如下关系表达式:

            a + x = s = nr;

            可得:a + x = (n - 1)r + r = (n - 1)r + (L - a)

            进一步得:a = (n - 1)r + (L -a - x)

结论:

1> (L - a -x)为相遇点到环入口节点的距离,即从相遇点开始向前移动(L -a -x)步后,会再次到达环入口节点。

2> 从链表的头节点到环入口节点的距离 = (n - 1) * 环内循环 + 相遇点到环入口点的距离。

3> 于是从链表头与相遇点分别设一个指针,每次各走一步,两个指针必定相遇,且相遇第一点为环入口点。

Node* EntryCircle(Node* head)

{

Node *slow = head, *fast = head;

while (fast && fast->next)

{

slow = slow->next;

fast = fast->next->next;

if (slow == fast)

{

while (head != slow)

{

head = head->next;

slow = slow->next;

}

return slow;

}

}

return NULL;

}

 

int GetLen(Node *head, Node *end)

{

int len = 0;

while (head != end)

{

head = head->next;

len++;

}

 

return len;

}

 

bool InSameCircle(Node* x, Node* y)

{

Node* next=x->next;

while(next!=x)

{

if(next==y) return true;

next=next->next;

}

return false;

}

 

Node* CrossNode(Node* x, Node* y)

{

if (x == NULL || y == NULL) return NULL;

 

Node* x1 = EntryCircle(x);

Node* y1 = EntryCircle(y);

if ((x1 != NULL && x1 == y1)

|| (x1 == NULL && y1 == NULL))

{

int len1 = GetLen(x, x1);

int len2 = GetLen(y, y1);

 

while (len1 > len2)

{

x = x->next;

len1--;

}

while (len2 > len1)

{

y = y->next;

len2--;

}

while (x)

{

if (x == y) return x;

x = x->next;

y = y->next;

}

}

else if(x1 != NULL && y1 != NULL && x1 != y1 && InSameCircle(x1, y1))

{

int len1 = GetLen(x, y1);

int len2 = GetLen(y, x1);

 

return (len1>len2?x1:y1);

}

 

return NULL;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值