判断链表是否有环,若有,返回第一个入环节点,若无,返回空。
快慢指针,若无环,快指针走到空,若有环,快慢指针相遇,然后快指针原地不动,慢指针回到头节点,快慢指针每次各走一步,相遇的节点为入环节点。
class Solution {
public:
ListNode *getLoopNode(ListNode *head){
ListNode *slow = head;
ListNode *fast = head;
while(slow && fast){
slow = slow -> next;
fast = (fast -> next) ? fast -> next -> next : nullptr;
if(slow == fast){
break;
}
}
if(slow == nullptr || fast == nullptr){
return nullptr;
}
slow = head;
while(slow != fast){
slow = slow -> next;
fast = fast -> next;
}
return slow;
}
};
【题目】给定两个可能有环也可能无环的单链表,头结点head1和head2.请实现一个函数,如果两个链表相交,请返回相交的第一个节点。如果不想交,返回null。
【要求】如果两个链表长度之和为N,时间复杂度请达到O(N),额外空间复杂度请达到O(1)。
使用getNodeLoop函数判断两个链表是否有环:
1)均无环:先计算两链表长度,长度差值为n,随后长链表先走n步,随后两链表同步移动,当移动到同一节点时,即为相交的第一个节点,若移动到null,两链表不相交。
2)一个有环一个无环:必不相交
3)均有环:
设getNodeLoop函数返回的两个节点指针为n1,n2.
若n1 n2指向相同的内存地址,则为情况2.
否则,让n1移动一圈回到n1,如果中途遇到n2,则为情况3,否则为情况1.
情况2找首个相交节点:把n1(也是n2)作为链表末尾,转化为找无环相交链表的首个相交节点。
情况3:返回n1/n2均可。
class Solution {
public:
ListNode *getLoopNode(ListNode *head){
ListNode *slow = head;
ListNode *fast = head;
while(slow && fast){
slow = slow -> next;
fast = (fast -> next) ? fast -> next -> next : nullptr;
if(slow == fast){
break;
}
}
if(slow == nullptr || fast == nullptr){
return nullptr;
}
slow = head;
while(slow != fast){
slow = slow -> next;
fast = fast -> next;
}
return slow;
}
ListNode* noLoop(ListNode *head1, ListNode *head2){
if(head1 == nullptr || head2 == nullptr){
return nullptr;
}
ListNode *cur1 = head1;
ListNode *cur2 = head2;
int n = 0;
while(cur1 -> next){
n++;
cur1 = cur1 -> next;
}
while(cur2 -> next){
n--;
cur2 = cur2 -> next;
}
if(cur1 != cur2){
return nullptr;
}
cur1 = n > 0 ? head1 : head2;
cur2 = cur1 == head1 ? head2 : head1;
n = n > 0 ? n : -n;
while(n != 0){
n--;
cur1 = cur1 -> next;
}
while(cur1 != cur2){
cur1 = cur1 -> next;
cur2 = cur2 -> next;
}
return cur1;
}
ListNode* bothLoop(ListNode *head1, ListNode *loop1, ListNode *head2, ListNode *loop2){
if(loop1 == loop2){
ListNode *cur1 = head1;
ListNode *cur2 = head2;
int n = 0;
while(cur1 != loop1){
n++;
cur1 = cur1 -> next;
}
while(cur2 != loop2){
n--;
cur2 = cur2 -> next;
}
cur1 = n > 0 ? head1 : head2;
cur2 = cur1 == head1 ? head2 : head1;
n = n > 0 ? n : -n;
while(n != 0){
cur1 = cur1 -> next;
n--;
}
while(cur1 != cur2){
cur1 = cur1 -> next;
cur2 = cur2 -> next;
}
return cur1;
}
else{
ListNode *cur = loop1 -> next;
while(cur != loop1){
if(cur == loop2){
return loop1;
}
cur = cur -> next;
}
return nullptr;
}
}
ListNode* getIntersectNode(ListNode *head1, ListNode *head2){
if(head1 == nullptr || head2 == nullptr){
return nullptr;
}
ListNode *loop1 = getLoopNode(head1);
ListNode *loop2 = getLoopNode(head2);
if(loop1 == nullptr && loop2 == nullptr){
return noLoop(head1, head2);
}
if(loop1 != nullptr && loop2 != nullptr){
return bothLoop(head1, loop1, head2, loop2);
}
return nullptr;
}
};