①链表是否有环,若有环,返回第一个入环节点?
方法:设置两个指针,快指针一次走两步,慢指针一次走一步,若快指针走到空节点,则说明无环,否则,等到两个指针在环内相遇,将快指针指向头节点,两个节点同时开始一次走一步,一定会在入环处相遇。
Node* getLoopNode(Node* root) {
if (root == nullptr || root->next == nullptr || root->next->next == nullptr)
return nullptr;
Node* slow = root->next;
Node* fast = root->next->next;
while (fast != slow) {
slow = slow->next;
if (fast == nullptr || fast->next == nullptr) return nullptr;
fast = fast->next->next;
}
fast = root;
while (fast != slow) {
fast = fast->next;
slow = slow->next;
}
return fast;
}
②链表是否相交,若相交,返回第一个相交节点?
方法:分情况讨论,若两个链表都无环,则可以先求出两个链表的长度n,m(n>m),并判断他们的最后一个节点是否相同,若不相同,则一定不相交,若相同,则先让长链表走n-m步,之后,另一个链表也开始走,判断他们的每一次节点是否相同,若相同,则说明返回即可;若两个链表有环,则先看两个链表的入环节点是否相同,若相同,则说明相交节点在入环节点前,
//先考虑无环情况和相交节点在公共入环节点前
Node* getNode(Node* root1, Node* root2, Node* N) {//N表示他们共同的入环节点
int size = 0;//记录链表1长度-链表2长度
Node* node1 = root1;
while (node1->next != N) {
size++;
node1 = node1->next;
}
Node* node2 = root2;
while (node2->next != N) {
size--;
node2=node2->next;
}
if (node1 != node2) return nullptr;
node1 = size > 0 ? root1 : root2;
node2 = node1 == root1 ? root2 : root1;
size = abs(size);
while (size-- != 0) node1 = node1->next;
while (node1 != node2) {
node1 = node1->next;
node2 = node2->next;
}
return node1;
}
Node* getFirstNode(Node* root1, Node* root2) {
Node* t1 = getLoopNode(root1);
Node* t2 = getLoopNode(root2);
if (t1 == nullptr && t2 == nullptr) {//说明无环
return getNode(root1, root2, nullptr);
}
else if (t1 != nullptr && t2 != nullptr) {//说明都有环
if (t1 == t2) {//说明在入环前相遇了。
return getNode(root1, root2, t1->next);
}
else {//则要么不相交,要么环内相交
Node* cur = t1->next;
while (cur != t1) {
if (cur == t2) return t2;
cur = cur->next;
}
return nullptr;
}
}
else {//说明一个有环,一个没有,则不可能相交
return nullptr;
}
}