1.求两个链表的交点
https://leetcode-cn.com/problems/intersection-of-two-linked-lists/description/
2.求环形链表的入环点
https://leetcode-cn.com/problems/linked-list-cycle-ii/description/
一、
首先要判断两个链表是否有交点。
可以通过遍历两个链表找到各自的尾结点,再比较两个尾结点是否相等,如果相等则证明相交,不相等则不相交(链表的相交和直线相交不一样,直线相交后朝各自的方向继续延伸,呈X形,而链表相交后由于交点的next一样,是往同一方向延伸的,呈Y形)
如果相交,找交点。
从各自的头开始遍历,计算出各自长度(假设为longlen、shortlen),区分出哪个长哪个短,再计算出长度差值的绝对值 num = abs(longlen-shortlen)。各自再次从头开始遍历,长链表先走num步,然后长短链表一起走,直到找到交点。(longlen-num=shortlen,长链表先走num步,这样当短链表开始走的时候长短链表会同时到达尾结点,同理也会同时到达交点)
ListNode* getIntersectionNode(ListNode* headA, ListNode* headB) {
if (headA == NULL || headB == NULL) {
return NULL;
}
//分别从两个头开始遍历,计算各自的路径长
ListNode* cur1 = headA;
ListNode* cur2 = headB;
int len1 = 0;
int len2 = 0;
while (cur1->next) {
cur1 = cur1->next;
len1++;
}
while (cur2->next) {
cur2 = cur2->next;
len2++;
}
//尾结点不相等则不相交
if (cur1 != cur2) {
return NULL;
}
//找出更大的
int lenlong = 0;
int lenshort = 0;
ListNode* longlist = NULL;
ListNode* shortlist = NULL;
if (len1 > len2) {
longlist = headA;
shortlist = headB;
}
else {
longlist = headB;
shortlist = headA;
}
//计算差值
int num = abs(len1 - len2);
//长的先走num步
while (num--) {
longlist = longlist->next;
}
//一起走
while (longlist != shortlist) {
longlist = longlist->next;
shortlist = shortlist->next;
}
return longlist;
}
二、
求入环点会用到找交点的知识
使用快慢指针可以判断是否有环
设快慢指针相遇点为meet,已知环形链表的头head1,把meet->next设为另一个头head2,如此我们就可以把一个环形链表拆成两个链表(head1~meet,head2~meet),这两个链表的交点就是入环点
ListNode* detectCycle(ListNode* head) {
//快慢指针遍历单链表,找到相遇点meet
//计算head到meet的距离len1,以及环的长度len2
//把head - meet和meet->next - meet各自看做一个链表
//接下来使用找两个交点的方式求解
ListNode* fast = head;
ListNode* slow = head;
while (fast && fast->next) {
fast = fast->next->next;
slow = slow->next;
if (slow == fast) {
int len1 = 0, len2 = 0;
//创建一个cur遍历,求len1和len2
ListNode* cur = head;
while (cur != slow) {
len1++;
cur = cur->next;
}
cur = slow->next;
while (cur != slow) {
len2++;
cur = cur->next;
}
//定义长短链表,默认从head开始长从meet->next开始短
ListNode* longlist = head;
ListNode* meet = slow;
ListNode* shortlist = meet->next;
if (len1 < len2) {
longlist = meet->next;
shortlist = head;
}
int gap = abs(len1 - len2);
//长的先走
while (gap--) {
longlist = longlist->next;
}
//一起走,相遇点则为入环点
while (longlist != shortlist) {
longlist = longlist->next;
shortlist = shortlist->next;
}
return longlist;
}
}
return NULL;
}