[Algorithm] Floyd's Cycle Detection์ด๋? (feat. Linked List)
์๋ ํ์ธ์ Foma ์ ๋๋ค!
์์ LeetCode์์ Linked List์ ์ฌ์ดํด์ ๊ด๋ จ๋ ๋ฌธ์ ๋ฅผ ํธ๋๋ฐ slow, fast ํฌ์ธํฐ๋ฅผ ๋ง์ด ์ด์ฉํ๋๋ผ๊ตฌ์.
ํด๋น ํ์ด๊ฐ ์ดํด๊ฐ ์๋ผ์ ์ฐพ์ ๋ณด๋ ๊ด๋ จ๋ ์๊ณ ๋ฆฌ์ฆ์ด ์์๊ณ , ๊ทธ๊ฒ์ด Floyd's Cycle Detection ์ด์์ต๋๋ค.
๊ทธ๋์ ์ค๋์ ๋งํฌ๋ ๋ฆฌ์คํธ์์ ์ฌ์ดํด์ด ์๋์ง ์๋์ง๋ฅผ ํ์ธํ ์ ์๊ณ , ํด๋น ์ฌ์ดํด์ ์์์ ์ด ์ด๋์ธ์ง ์์๋ผ ์ ์๋ Floyd's Cycle Detection ์ ๋ํด์ ์์๋ณด๋ ค๊ณ ํฉ๋๋ค.
๋ฐ๋ก ์์ํ ๊ฒ์~
Floyd's Cycle Detection ์ด๋? ๐
Robert W. Floyd๊ฐ ๊ณ ์ํ ๋ฆฌ์คํธ์ ์ฌ์ดํด์ ๋น ๋ฅด๊ณ ์ ์ ๋ฉ๋ชจ๋ฆฌ๋ก ์ฐพ๋ ์๊ณ ๋ฆฌ์ฆ์ ๋๋ค.
(Robert W. Floyd๋ ํ๋ก์ด๋ ์์ฌ ์๊ณ ๋ฆฌ์ฆ์ ๋ง๋ค์ด๋ธ ์ฌ๋๊ณผ ๋์ผ ์ธ๋ฌผ์ ๋๋ค.)
๊ฑฐ๋ถ์ด์ ํ ๋ผ (Tortoise and Hare) ์๊ณ ๋ฆฌ์ฆ์ผ๋ก๋ ๋ง์ด ์๋ ค์ ธ ์์ต๋๋ค.
์ ๊ฑฐ๋ถ์ด์ ํ ๋ผ ์๊ณ ๋ฆฌ์ฆ์ผ๊น? ๐ค
๋ฐ๋ก ๊ฑฐ๋ถ์ด์ฒ๋ผ ๋๋ฆฌ๊ฒ ์์ง์ด๋ ํฌ์ธํฐ์ ํ ๋ผ์ฒ๋ผ ๋น ๋ฅด๊ฒ ์์ง์ด๋ ํฌ์ธํฐ ์ด๋ ๊ฒ ์ด ๋ ํฌ์ธํฐ๊ฐ ํ์ํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
Example
์๋์ ๊ฐ์ด ์ฌ์ดํด์ด ์๋ ๋งํฌ๋ ๋ฆฌ์คํธ๊ฐ ์๋ค๊ณ ๊ฐ์ ํ๊ฒ ์ต๋๋ค.
๊ทธ ๋ค์ ์ฌ์ดํด์ด ์์๋๋ ์ง์ ์ ์ฐพ์ ๋ณด๊ฒ ์ต๋๋ค.
0 1 2 3 4 5 6 7 8 3 4 5 6 7 8 ... ์ผ๋ก 3๋ถํฐ 8๊น์ง ์ฌ์ดํด์ด ์กด์ฌํ๋ ๋ฆฌ์คํธ์ ๋๋ค.
1. ๊ฐ์ฅ ์ฒ์ ๊ฑฐ๋ถ์ด์ ํ ๋ผ๊ฐ ๋ง๋๋ ์ง์ ์ ๊ตฌํ๋ค.
๋จผ์ ๊ฑฐ๋ถ์ด(๋๋ฆฌ๊ฒ ์ด๋ํ๋ ํฌ์ธํฐ)์ ํ ๋ผ(๋น ๋ฅด๊ฒ ์ด๋ํ๋ ํฌ์ธํฐ)๋ฅผ ๊ฐ์ฅ ์ฒซ ๋ฒ์งธ(head)์ ์์นํฉ๋๋ค.
๊ฑฐ๋ถ์ด๋ ํ ์นธ์ฉ ํ ๋ผ๋ ๋ ์นธ์ฉ ์ด๋ํ๋ฉด ์๋์ ๊ฐ์ด ์งํ๋ฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์๋ก ๋ง๋๊ฒ ๋๋ ์ง์ ์ 6์ด ๋์ฃ .
(๋ง์ฝ ํ ๋ผ์ ๊ฑฐ๋ถ์ด๊ฐ ๋ง๋๋ ์ง์ ์ด ์๋ค๋ฉด ์ฌ์ดํด์ด ์๋ค๋ ์๋ฏธ์ ๋๋ค.)
2. ๊ฑฐ๋ถ์ด๋ฅผ ์ฒซ ๋ฒ์งธ ์ง์ ์ผ๋ก ๋๋๋ฆฌ๊ณ , ํ ๋ผ์ ๊ฑฐ๋ถ์ด ๋ ๋ค ํ ์นธ์ฉ ์ด๋ํ๋ฉฐ ๋ค์ ๋ง๋๋ ์ง์ ์ ๊ตฌํ๋ค.
์ด์ ๊ฑฐ๋ถ์ด๋ฅผ ๊ฐ์ฅ ์ฒซ ๋ฒ์งธ๋ก ๋ค์ ๋๋๋ฆฝ๋๋ค.
๊ทธ ๋ค์๋ถํฐ๋ ํ ๋ผ๋ ๊ฑฐ๋ถ์ด์ ๊ฐ์ด ํ ์นธ์ฉ๋ง ์ด๋ํ ์ ์์ต๋๋ค.
์ด๋ฐ ์์ผ๋ก ์ด๋ํ๋ฉด ํ ๋ผ์ ๊ฑฐ๋ถ์ด ์๋ก ๋ง๋๋ ์ง์ ์ 3์ด ๋ฉ๋๋ค.
์ด๊ฒ์ ์ฌ์ดํด์ด ์์๋๋ ์ง์ ์ด ๋๋ ๊ฒ์ด์ฃ .
Proof
X: ์์์ ๋ถํฐ ์ฌ์ดํด์ด ๋ฐ์ํ๊ธฐ ์ ๊น์ง ๊ธธ์ด
Y: ์ฌ์ดํด ์์์ ๋ถํฐ ์ฒซ ๋ฒ์งธ ๋ง๋๋ ์ง์ ์ ๊น์ง ๊ธธ์ด
Z: ์ฒซ ๋ฒ์งธ ๋ง๋๋ ์ง์ ๋ถํฐ ์ฌ์ดํด ์์์ ์ ๊น์ง ๊ธธ์ด
C: ์ฌ์ดํด์ ๊ธธ์ด
M: ๋ง๋๋ ์ง์
๋ ์นธ์ฉ ์ด๋ํ ๊ฒฝ์ฐ ์ฒซ ๋ฒ์งธ ๋ง๋๋ ์ง์ ๊น์ง ์ด๋ํ ๊ฑฐ๋ฆฌ๋ฅผ ๊ณ์ฐํ๋ฉด ์๋์ ๊ฐ์ต๋๋ค.
์ฌ์ดํด์ด ์์๋๊ธฐ ์ X๋งํผ ์ด๋ํ๊ณ ์ฌ์ดํด์ rโ๋ฐํด ๋๊ณ Y๋งํผ ์ด๋ํด M์ง์ ์์ ๊ฑฐ๋ถ์ด๋ฅผ ๋ง๋๊ฒ ๋ฉ๋๋ค.
h = x + rโc + y
ํ ์นธ์ฉ ์ด๋ํ ๊ฒฝ์ฐ ์ฒซ ๋ฒ์งธ ๋ง๋๋ ์ง์ ๊น์ง ์ด๋ํ ๊ฑฐ๋ฆฌ๋ฅผ ๊ณ์ฐํ๋ฉด ์๋์ ๊ฐ์ต๋๋ค.
์ฌ์ดํด์ด ์์๋๊ธฐ ์ X๋งํผ ์ด๋ํ๊ณ ์ฌ์ดํด์ rโ๋ฐํด ๋๊ณ Y๋งํผ ์ด๋ํด M์ง์ ์์ ํ ๋ผ๋ฅผ ๋ง๋๊ฒ ๋ฉ๋๋ค.
t = x + rโc + y
ํ ๋ผ๋ ๋ ์นธ์ฉ, ๊ฑฐ๋ถ์ด๋ ํ ์นธ์ฉ ์์ง์ด๋ฏ๋ก ๋ค๋ฅธ ์์ผ๋ก ์๋์ ๊ฐ์ด ์ธ ์ ์์ต๋๋ค.
2T = H
์ฆ, ์๋์ ๊ฐ์ด ํ์ด ์ธ ์ ์์ฃ .
2(x + rโc + y) = x + rโc + y
-> 2x + 2rโc + 2y = x + rโc + y
-> 2x + 2y - x - y = rโc - 2rโc
-> x + y = (rโ - 2rโ)c
-> x = (rโ - 2rโ)c - Y
-> x = (rโ - 2rโ - 1)c + c -y
์ด ๋ rโ - 2rโ - 1์ ์์์ด๋ฏ๋ก rโ๋ผ๋ ์๋ก์ด ์์๋ฅผ ๋ง๋ค์ด ๋์ฒด์์ผ ์ค๋๋ค.
x = rโc + c - y
c๋ ์ฌ์ดํด์ด๋ฏ๋ก ๋ค๋ฅธ ๋ง๋ก y + z๊ฐ ๋ ์ ์์ต๋๋ค.
x = rโc + y + z - y
-> x = rโc + z
์ฆ, ์์์ ๋ถํฐ ์ฌ์ดํด์ด ์์๋๊ธฐ ์ ๊น์ง์ ๊ธธ์ด๋(x) ์ฌ์ดํด์ rโ๋งํผ ๋๊ณ ๋ง๋ ์ง์ ๋ถํฐ ์ฌ์ดํด์ด ์์์ ๊น์ง์ ๊ธธ์ด(z)์ ๊ฐ๋ค๊ฐ ์ฑ๋ฆฝ๋ฉ๋๋ค.
๊ณ ๋ก ์ฒซ ๋ฒ์งธ๋ก ๋ง๋ ์ง์ ๋ถํฐ ์์์ ๊น์ง ์ฐจ๋ก๋ก ํ ์นธ์ฉ ์ด๋ํ๋ฉด ์ฌ์ดํด์ ์์์ ์ ์ ์ ์๊ฒ ๋๋ ๊ฒ์ด์ฃ .
Code
์๋์ ๊ฐ์ด ํ๋ผ๋ฏธํฐ๋ก ListNode๋ฅผ ๋ฐ๊ณ , ์ฌ์ดํด์ ์์์ธ ListNode๋ฅผ ๋ฐํํ๋ ์ฝ๋๋ฅผ ์์ฑํด ๋ณด๊ฒ ์ต๋๋ค.
func floydCycleDetection(_ head:ListNode?) -> ListNode? {
๋จผ์ ํ ์นธ์ฉ ์์ง์ผ ๊ฑฐ๋ถ์ด(tortoise)์ ๋ ์นธ์ฉ ์์ง์ผ ํ ๋ผ(hare)๋ฅผ ๊ฐ์ฅ ์ฒ์ ๋ ธ๋์ธ head๋ก ์ค์ ํด ์ค๋๋ค.
var tortoise = head
var hare = head
while๋ฌธ์ ์ด์ฉํด tortoise๋ next๋ก ํ ์นธ์ฉ, hare๋ next?.next๋ก ๋ ์นธ์ฉ ์ด๋ํด ์ค๋๋ค.
๋ง์ฝ tortorise์ hare๊ฐ ๊ฐ๋ค๋ฉด while๋ฌธ์ ๋ฉ์ถฐ ์ค๋๋ค.
while true {
tortoise = tortoise?.next
hare = hare?.next?.next
if tortoise === hare {
break
}
}
๊ฑฐ๋ถ์ด๋ฅผ ๋ค์ ์ฒ์์ผ๋ก ๋๋๋ ค ์ค๋๋ค.
tortoise = head
์ด๋ฒ์ tortoise์ hare ๋ ๋ค ๋๊ฐ์ด next๋ก ํ ์นธ์ฉ๋ง ์ด๋์์ผ ์ค๋๋ค.
๋ง์ฝ tortorise์ hare๊ฐ ๊ฐ๋ค๋ฉด while๋ฌธ์ ๋ฉ์ถฐ ์ค๋๋ค.
while true {
tortoise = tortoise?.next
hare = hare?.next
if tortoise === hare {
break
}
}
tortoise ๋๋ hare๋ฅผ ๋ฐํํด ์ฃผ๋ฉด ์ฌ์ดํด์ ์์์ (3)์ด ๋ฐํ๋ฉ๋๋ค.
return tortoise //value: 3
Reference