给定一个链表,返回链表开始入环的第一个节点。 从链表的头节点开始沿着 next 指针进入环的第一个节点为环的入口节点。如果链表无环,则返回 null。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。
这题,我首先想到的是利用哈希表的方法,每一个节点为key,value值为节点的next。这样写很简便,但是需要额外的数据结构
///哈希表//
ListNode *detectCycle1(ListNode *head) {
if(head == nullptr)
return nullptr;
unordered_map<ListNode*,ListNode*> MyNodeMap;
while(head->next != nullptr)
{
if(MyNodeMap.find(head)==MyNodeMap.end())
{
MyNodeMap[head]=head->next;
head = head->next;
}
else
return head;
}
return nullptr;
}
第二种方法是利用快慢指针。
首先,快指针一次走两步,慢指针一次走一步,若有环则快慢指针一定会相遇
(在这一步中,一旦快指针到空,则一定无环)
相遇后,快指针回到头节点,快慢指针每次各走一步,两个指针将会在第一个环节点相遇。
//快慢指针
ListNode *detectCycle(ListNode *head) {
if(head == nullptr)
return nullptr;
ListNode* FNode = head; //快指针
ListNode* SNode = head; //慢指针
while(FNode!=nullptr && FNode->next!=nullptr)
{
FNode=FNode->next->next;
SNode = SNode->next;
if(FNode == SNode) //此时快慢指针相遇
break;
}
if(FNode == nullptr || FNode->next == nullptr)
return nullptr;
FNode = head; //快指针回到头节点
while(FNode != SNode)
{
FNode=FNode->next;
SNode=SNode->next;
}
return SNode;
}