-
Notifications
You must be signed in to change notification settings - Fork 43
/
linked-list-cycle-ii.py
220 lines (192 loc) · 5.82 KB
/
linked-list-cycle-ii.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
"""
142. Linked List Cycle II
Medium
Given the head of a linked list, return the node where the cycle begins. If there is no cycle, return null.
There is a cycle in a linked list if there is some node in the list that can be reached again by continuously following the next pointer. Internally, pos is used to denote the index of the node that tail's next pointer is connected to (0-indexed). It is -1 if there is no cycle. Note that pos is not passed as a parameter.
Do not modify the linked list.
Example 1:
Input: head = [3,2,0,-4], pos = 1
Output: tail connects to node index 1
Explanation: There is a cycle in the linked list, where tail connects to the second node.
Example 2:
Input: head = [1,2], pos = 0
Output: tail connects to node index 0
Explanation: There is a cycle in the linked list, where tail connects to the first node.
Example 3:
Input: head = [1], pos = -1
Output: no cycle
Explanation: There is no cycle in the linked list.
Constraints:
The number of the nodes in the list is in the range [0, 104].
-105 <= Node.val <= 105
pos is -1 or a valid index in the linked-list.
Follow up: Can you solve it using O(1) (i.e. constant) memory?
"""
# V0
# IDEA : 2 pointers + linked list basics
# https://github.com/yennanliu/CS_basics/blob/master/doc/cheatsheet/2_pointers.md
class Solution:
def detectCycle(self, head):
if not head or not head.next:
return
slow = fast = head
while fast and fast.next:
fast = fast.next.next
slow = slow.next
if fast == slow:
break
#print ("slow = " + str(slow) + " fast = " + str(fast))
### NOTE : via below condition check if is a cycle linked list
if not fast or not fast.next:
return
"""
### NOTE : re-init slow or fast as head (from starting point)
-> can init slow or head
"""
slow = head
#fast = head
"""
### NOTE : check while slow != fast
### NOTE : use the same speed
"""
while slow != fast:
fast = fast.next
slow = slow.next
return slow
# V0'
# IDEA : SET
class Solution(object):
def detectCycle(self, head):
if not head or not head.next:
return
s = set()
while head:
s.add(head)
head = head.next
if head in s:
return head
return
# V0'
# IDEA : SET
class Solution(object):
def detectCycle(self, head):
if not head: return None
visited = set()
while head:
if head in visited:
return head
visited.add(head)
head = head.next
return None
# V1
# https://blog.csdn.net/fuxuemingzhu/article/details/79530638
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
slow, fast = head, head
while fast and fast.next:
fast = fast.next.next
slow = slow.next
if fast == slow:
break
if not fast or not fast.next:
return None
slow = head
while slow != fast:
slow = slow.next
fast = fast.next
return fast
# V1'
# https://blog.csdn.net/fuxuemingzhu/article/details/79530638
# IDEA : SET
class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if not head: return None
visited = set()
while head:
if head in visited:
return head
visited.add(head)
head = head.next
return None
# V1''
# http://bookshadow.com/weblog/2015/07/10/leetcode-linked-list-cycle-ii/
class Solution:
# @param head, a ListNode
# @return a list node
def detectCycle(self, head):
if head is None or head.next is None:
return None
slow, fast = head.next, head.next.next
while fast and fast.next and slow != fast:
fast = fast.next.next
slow = slow.next
if fast is None or fast.next is None:
return None
slow = head
while slow != fast:
slow, fast = slow.next, fast.next
return slow
# V2
# https://www.cnblogs.com/zuoyuan/p/3701877.html
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# @param head, a ListNode
# @return a list node
def detectCycle(self, head):
if head == None or head.__next__ == None:
return None
slow = fast = head
while fast and fast.__next__:
slow = slow.__next__
fast = fast.next.__next__
if fast == slow:
break
if slow == fast:
slow = head
while slow != fast:
slow = slow.__next__
fast = fast.__next__
return slow
return None
# V3
# Time: O(n)
# Space: O(1)
class ListNode(object):
def __init__(self, x):
self.val = x
self.next = None
def __str__(self):
if self:
return "{}".format(self.val)
else:
return None
class Solution(object):
# @param head, a ListNode
# @return a list node
def detectCycle(self, head):
fast, slow = head, head
while fast and fast.__next__:
fast, slow = fast.next.__next__, slow.__next__
if fast is slow:
fast = head
while fast is not slow:
fast, slow = fast.__next__, slow.__next__
return fast
return None