master
1<<-DOC
2You are given a single linked list, and you are asked to determine if there is a circle inside it
3A circle means, a -> b -> c -> b, then it is a circle
4
5Part 2.
6Could you get the length of the circle for the input single linked list if there is one,
7or output 0 if there is no circle? (O(1) space and O(n) time complexity)
8
9A -> B -> C -> D -> E -> F -> D
10|T|H|
11|A|B|
12|B|D|
13|C|F|
14|D|E|
15|E|D|
16
17Part 3.
18could you find the entry point of the circle?
19which means the point A for (a->b->c->a)
20DOC
21
22describe "cycle" do
23 def circle?(head)
24 return false if head.nil?
25
26 tortoise, hare = head, head.next_item
27
28 until hare.nil?
29 return true if tortoise == hare
30 tortoise, hare = tortoise.next_item, hare.next_item&.next_item
31 end
32
33 false
34 end
35
36 def cycle_length(head)
37 return 0 if head.nil?
38
39 tortoise, hare = head, head.next_item
40
41 detected = false
42 count = 0
43
44 until hare.nil?
45 if tortoise == hare
46 return count if detected
47 detected = true
48 end
49 count += 1 if detected
50 tortoise, hare = tortoise.next_item, hare.next_item&.next_item
51 end
52 0
53 end
54
55 def cycle_length(head)
56 return 0 if head.nil?
57
58 tortoise, hare = head, head
59 d1, d2 = 0, 0
60
61 while hare && tortoise
62 break if tortoise == hare && hare != head
63
64 tortoise, hare = tortoise.next_item, hare.next_item&.next_item
65 d1 += 1
66 d2 += 2
67 end
68 return 0 if hare.nil?
69
70 d2 - d1
71 end
72
73 def entry_point(head)
74 return nil if head.nil?
75
76 tortoise, hare = head, head.next_item
77
78 until hare.nil?
79 break if tortoise == hare
80 tortoise, hare = tortoise.next_item, hare.next_item&.next_item
81 end
82
83 tortoise = head
84 until hare == tortoise
85 tortoise = tortoise.next_item
86 hare = hare.next_item
87 end
88 return tortoise
89 end
90
91 def entry_point(head)
92 return nil if head.nil?
93
94 tortoise, hare = head, head.next_item
95
96 until hare.nil?
97 break if tortoise == hare
98 tortoise, hare = tortoise.next_item, hare.next_item&.next_item
99 end
100
101 return nil if tortoise.nil? || hare.nil?
102
103 visited = {}
104 tortoise = head
105 until hare == tortoise
106 tortoise = tortoise.next_item
107 hare = hare.next_item
108 return hare if visited[hare]
109
110 visited[hare] = true
111 end
112 return tortoise
113 end
114
115 class Node
116 attr_reader :next_item, :value
117
118 def initialize(value)
119 @value = value
120 end
121
122 def add(value)
123 @next_item = value.is_a?(Node) ? value : Node.new(value)
124 end
125
126 def inspect
127 "#{object_id} #{value}"
128 end
129 end
130
131 it do
132 a = Node.new("A")
133 b = Node.new("B")
134 c = Node.new("C")
135
136 a.add(b)
137 b.add(c)
138 c.add(b)
139 expect(circle?(a)).to be_truthy
140 expect(cycle_length(a)).to eql(2)
141 end
142
143
144 <<-DOC
145A -> B -> C -> D -> E -> F -> D
146
147|T|H|
148|A|B|
149|B|D|
150|C|F|
151|D|E|
152|E|D|
153 DOC
154
155 it do
156 a = Node.new("A")
157 b = Node.new("B")
158 c = Node.new("C")
159 d = Node.new("D")
160 e = Node.new("E")
161 f = Node.new("F")
162
163 a.add(b)
164 b.add(c)
165 c.add(d)
166 d.add(e)
167 e.add(f)
168 f.add(d)
169
170 expect(circle?(a)).to be_truthy
171 expect(cycle_length(a)).to eql(3)
172 end
173
174 it do
175 a = Node.new("A")
176 b = Node.new("B")
177
178 a.add(b)
179
180 expect(circle?(a)).to be_falsey
181 expect(cycle_length(a)).to eql(0)
182 end
183
184 it 'detects the entry point' do
185 # (a->b->c->a)
186 # a|b
187 # b|a
188 # c|c
189 a = Node.new("A")
190 b = Node.new("B")
191 c = Node.new("C")
192 a.add(b)
193 b.add(c)
194 c.add(a)
195
196 expect(entry_point(a)).to eql(a)
197 end
198
199
200 it 'detects entry point' do
201 # A -> B -> C -> D -> C is C the entry point
202 a = Node.new("A")
203 b = Node.new("B")
204 c = Node.new("C")
205 d = Node.new("D")
206 a.add(b)
207 b.add(c)
208 c.add(d)
209 d.add(c)
210
211 expect(entry_point(a)).to eql(c)
212 end
213
214 it 'finds no entry point' do
215 #(a->b->c)
216 a = Node.new("A")
217 b = Node.new("B")
218 c = Node.new("C")
219 a.add(b)
220 b.add(c)
221
222 expect(entry_point(a)).to be_nil
223 end
224end