Given a linked list, return the node where the cycle begins. If there is no cycle, return null
.
Follow up:
Can you solve it without using extra space?
解法一: 哈希,需要O(n)的空间复杂度,时间复杂度是O(n)
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
if(head == null || head.next == null)
return null;
HashSet<ListNode> hash = new HashSet<ListNode>();
ListNode cur = head;
ListNode res = null;
while(cur.next != null)
{
if(hash.size() == 0 || !hash.contains(cur))
{ hash.add(cur); cur = cur.next;}
else
{
res = cur;
break;
}
}
hash = null;
return res;
}
}
解法二:O(1)的空间复杂度,O(n^2)的空间复杂度:
/**
* 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) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
if(head == NULL || head->next == NULL)
return NULL;
ListNode *cur = head;
if(cur->next == cur)
return cur;
while(cur->next != NULL)
{
if(isnode(cur))
return cur;
cur = cur->next;
}
return NULL;
}
bool isnode(ListNode *cur)
{
ListNode *after = cur->next;
while(after != NULL)
{
if(after == cur)
return true;
after = after->next;
}
return false;
}
};
很奇怪:Last executed input:{3,2,0,-4}, tail connects to node index 1
这组数据,怎么会超时?
下面有位朋友给了一个国外大神的链接,该算法确实神奇,当两个指针相遇后,让另一个指针指向头,然后一起移动,当
两个指针再次相遇的时候,指针的结点就是圈的开始结点,多么神奇啊,研究了一下,得到了一个重要的结论,让 n 为循环圈的长度,即
n 个结点,让 m 为相遇结点到头结点之间的结点数,那么 n == m ,有了这个结论就不难理解为什么算法是正确的 了。膜拜一下大神!