leetcode142-环形链表 II
142. 环形链表 II
方法一:快慢指针
先通过快指针和慢指针判断是否有环,无环则返回NULL.
有环:
概括来说就是:f 代表快指针走了几步,s 代表慢指针走了几步。则有 f = 2s ; f = s + nb ; (b代表环的结点个数,n代表快指针比慢指针多走几个环的长度)
两式联立得,f = 2nd ; s = nb ;
如果让慢指针再走从起始结点到环入口的距离a,慢指针将回到环入口,即 s2 = a + nb;
如何知道起始结点到环入口的距离a?可以让一个指针从起始结点不断向前走一步,和慢指针相遇的地方就是环的入口。这里我们使用快指针每次走一步。
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode *detectCycle(ListNode *head) { ListNode *dummyHead = new ListNode; dummyHead->next=head; ListNode *slow=dummyHead; ListNode *fast=dummyHead; while(slow&&fast&&fast->next) { slow=slow->next; fast=fast->next->next; if(slow==fast) break; } if(!(slow&&fast&&fast->next)) return NULL; fast = dummyHead; while(fast!=slow) { fast=fast->next; slow=slow->next; } return slow; };
方法二:哈希表?集合?如果出现第一个已在集合中的结点,那它就是环的入口
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode *detectCycle(ListNode *head) { unordered_set<ListNode*> code; while(head) { if(code.count(head)) return head; code.insert(head); head=head->next; } return NULL; } };