方法一(set容器):
(1)将链表中节点的指针插入set容器
(2)在遍历插入节点时,在set容器中查找该节点是否存在。
(3)第一个已存在的节点即为链表环的起点。
//链表求环 方法一
ListNode* detectCycle(ListNode* head)
{
std::set<ListNode*> node_set;
while (head)
{
if (node_set.find(head) != node_set.end())
return head;
node_set.insert(head);
head = head->next;
}
return NULL;
}
方法二(快慢指针):
(1)快指针每次走2步,满指针每次走一步。
(2)当快指针与满指针相遇时,证明有环,相遇点为meet。
(3)meet和head到环的起点的距离相等。(数学证明)
//链表求环 方法二
ListNode* selectCycle(ListNode* head)
{
ListNode *fast = head;
ListNode *slow = head;
ListNode *meet = NULL;
while (fast)
{
slow = slow->next;
fast = fast->next;
if (!fast)
{
return NULL;
}
fast = fast->next;
if (fast == slow)
{
meet = fast;
break;
}
}
if (meet == NULL)
{
return NULL;
}
while (head&&meet)
{
if (head == meet)
{
return head;
}
head = head->next;
meet = meet->next;
}
return NULL;
}