Given a linked list, determine if it has a cycle in it.

Can you solve it without using extra space?

 

每个节点再开辟一个属性存放是否访问过,这样遍历一遍即可知道是否有环。

但为了不增加额外的空间,

可以设置两个指针,一个一次走一步,另一个一次走两步,如果有环则两个指针一定会再次相遇,反之则不会。

 

C++:

 1 class Solution {
 2 public:
 3     bool hasCycle(ListNode *head) {
 4         if(head==NULL||head->next==NULL) return 0;
 5 
 6         ListNode *p=head;
 7         ListNode *q=head;
 8         int flag=0;
 9         while(p->next)
10         {
11             if(p->next==q)
12             {
13                 flag=1;
14                 break;
15             }
16             p=p->next;
17             if(p->next==NULL)
18                 break;
19             p=p->next;
20             q=q->next;
21         }
22         if(flag==1)
23             return 1;
24         else
25             return 0;
26     }
27 };

 

Python:

 1 # Definition for singly-linked list.
 2 # class ListNode:
 3 #     def __init__(self, x):
 4 #         self.val = x
 5 #         self.next = None
 6 
 7 class Solution:
 8     # @param head, a ListNode
 9     # @return a boolean
10     def hasCycle(self, head):
11         if head is None:
12             return False
13         p1=head
14         p2=head
15         while True:
16             if p1.next is not None:
17                 p1=p1.next.next
18                 p2=p2.next
19                 if p1 is None or p2 is None:
20                     return False
21                 elif p1==p2:
22                     return True
23             else:
24                 return False
25         return False

 

II:

 

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?

 

当fast与slow相遇时,

slow肯定没有遍历完链表,而fast已经在环内循环了$n$圈($1 \leq n$)。假设slow走了$s$步,则fast走了$2s$步(fast步数还等于$s$加上在环上多转的$n$圈),设环长为$r$,则:

2s=s+nr
s=nr

设整个链表长$L$,环入口点与相遇点距离为$a$,起点到环入口点的距离为$x$,则

x+ax=nr=(n1)r+r=(n1)r+Lx
x=(n1)r+(Lxa)

$L – x – a$为相遇点到环入口点的距离,由此可知,从链表头到环入口点等于$n-1$圈内环+相遇点到环入口点,

于是我们可以从{head}开始另设一个指针{slow2},两个慢指针每次前进一步,它俩一定会在环入口点相遇。

分析来自 ACM之家。

 1 class Solution {
 2 public:
 3     ListNode *detectCycle(ListNode *head) {
 4         if(head==NULL||head->next==NULL) return NULL;
 5         ListNode *p=head;
 6         ListNode *q=head;
 7         while(p->next&&p->next->next)
 8         {
 9             q=q->next;
10             p=p->next->next;
11             if(q==p)
12             {
13                 q=head;
14                 while(q!=p)
15                 {
16                     p=p->next;
17                     q=q->next;
18                 }
19                 
20                 return q;
21             }
22         }
23         
24         return NULL;
25     }
26 };

 

posted on 2015-04-07 23:46  黄瓜小肥皂  阅读(146)  评论(0编辑  收藏  举报