"두 러너를 다른 속도로 리스트에 보내. 그 사이 간격은 무작위가 아니야 — 가운데 찾기, 고리 잡기, 끝에서 n번째 닿기를 한 패스에 추가 메모리 없이 하려고 써먹을 수 있는 사실이야."
아이디어: 두 속도, 한 패스
연결 리스트는 인덱싱을 못 해서, 배열에서 통하는 트릭 (가운데로 점프, 끝에서 n번째 엿보기) 이 두 패스 없이는 불가능해 보여. 빠른/느린 포인터 기법은 두 포인터를 다른 속도로 달리며 그 사이 관계를 읽어 한 패스에 얻어. Arrays 트랙의 투 포인터랑 같은 가문, 걷기만 되는 연결 리스트 세계에 특화된 거야.
가운데 찾기, 한 패스에
slow 를 한 번에 한 노드, fast 를 한 번에 두 노드 움직여. fast 가 끝에 닿으면, slow 가 간 거리의 두 배를 간 거야 — 그래서 slow 가 정확히 가운데 앉아 있어. 한 순회, 길이 세기 없음, 두 번째 패스 없음. 반칙처럼 느껴지는데 그냥 산수야: 절반 속도, 절반 거리.
플로이드 순환 검출: 유명한 그것
연결 리스트에 고리 (자기 next 가 리스트로 되돌아 가리키는 노드) 가 있어? 순진한 답은 방문한 모든 노드를 set 에 저장 — O(n) 공간. 플로이드의 토끼와 거북이는 O(1) 공간에 해: slow (×1) 랑 fast (×2) 를 달려. 고리가 없으면 fast 가 끝에서 떨어져 (None 에 닿음). 고리가 있으면 fast 가 계속 돌며 결국 slow 랑 정확히 같은 노드에 착지해 — 충돌해. 두 포인터, 추가 메모리 없음, 그리고 진짜 아름다운 추론: 고리 안에서 ×2 러너가 ×1 러너한테 틱당 한 칸씩 좁혀, 그래서 결국 따라잡을 수밖에 없어.
세지 않고 끝에서 n번째
끝에서 n 위치 노드를 원하는데 길이를 몰라? fast 를 먼저 혼자 n 단계 전진시키고, 그다음 fast 가 끝에 닿을 때까지 fast 랑 slow 를 같이 움직여. fast 가 내내 정확히 n 앞에 있었어서, slow 가 정확히 끝에서 n 에 착지해. 한 패스, 길이 불필요 — 고정된 간격이 세기를 대신해줬어.