287. Find the Duplicate Number

  • 처음 λ΄€μ„λ•Œ sorting μ΄λ‚˜ set을 μ“°λ©΄ λ˜κ² μ§€ ν–ˆμ§€λ§Œβ€¦ arrayλ₯Ό μˆ˜μ •ν•  수 μ—†κ³ , constant storage complexity O(1), linear time complexity O(n) μ œμ•½ 쑰건이 μžˆμ–΄μ„œ μ‚¬μš©ν•  수 μ—†μ–΄μ„œ μ–΄λ €μ› λ˜ λ¬Έμ œμ΄λ‹€.
  • Floyd's Tortoise and Hare μ•Œκ³ λ¦¬μ¦˜μ„ μ‚¬μš©ν•΄μ•Ό ν•œλ‹€.
    • Linked listμ—μ„œ cycle이 μ‘΄μž¬ν•  λ•Œ cycle의 μ‹œμž‘μ μ„ 찾을 수 μžˆλŠ” μ•Œκ³ λ¦¬μ¦˜μ΄λ‹€.
    • κ·Έλž˜ν”„μ˜ λͺ¨μ–‘은 풍선 (cycle) 끝에 μ„  (index 0 μ‹œμž‘μ )이 λΆ™μ–΄μžˆλŠ” λͺ¨μ–‘이 λœλ‹€.
  • λ¬Έμ œλŠ” cycle의 μ‹œμž‘μ μ΄ μ–΄μ§Έμ„œ μ€‘λ³΅λœ 값일 수 μžˆλŠ”κ°€ ν•˜λŠ” 점이닀.
    • μ΄λŠ” array에 μ€‘λ³΅λœ 값이 μžˆμ„ 경우 κ·Έλž˜ν”„μ—μ„œ μ€‘λ³΅λœ 값에 λŒ€ν•œ λ…Έλ“œλ§Œμ΄ μœ μΌν•˜κ²Œ λ“€μ–΄μ˜€λŠ” 연결이 2개 이상이기 λ•Œλ¬Έμ΄λ‹€.
    • λ‚˜λ¨Έμ§€ 값에 ν•΄λ‹Ήν•˜λŠ” λ…Έλ“œλŠ” λ“€μ–΄μ˜€λŠ” 연결이 ν•˜λ‚˜μ΄λ―€λ‘œ index 0 μ‹œμž‘μ  β†’ cycle의 μ‹œμž‘μ  λ˜λŠ” cycle 내뢀에 μœ„μΉ˜ν•˜κ²Œ λœλ‹€.
      • λ¬Όλ‘  일뢀 λ…Έλ“œλŠ” index 0 μ‹œμž‘μ  μ„ μ—μ„œ λ‹ΏλŠ” cycle을 ν˜•μ„±ν•˜λŠ”λ°μ—μ„œ μ œμ™Έλ  수 μžˆλ‹€.
    • μ•„λž˜ 그림은 이해λ₯Ό 돕기 μœ„ν•΄μ„œ index 0을 ν¬ν•¨μ‹œμΌ°μ§€λ§Œ μ•Œκ³ λ¦¬μ¦˜μ—μ„œλŠ” index 0이 κ°€λ¦¬ν‚€λŠ” 지점 λΆ€ν„° μ‹œμž‘ν•œλ‹€.
      • λ¬Όλ‘  index 0으둜 μ‹œμž‘ν•΄λ„ κ²°κ³ΌλŠ” κ°™λ‹€.
      notion image
  • μ•Œκ³ λ¦¬μ¦˜μ΄ λ™μž‘ν•˜λŠ” μ›λ¦¬λŠ” λ‹€μŒκ³Ό κ°™λ‹€.
쑰건 index 0 μ‹œμž‘μ  β†’ cycle의 μ‹œμž‘μ κΉŒμ§€μ˜ 길이λ₯Ό m, cycle의 길이λ₯Ό n이라고 ν•˜μž. λ‘˜μ΄ λ§Œλ‚˜κΈ°κΉŒμ§€ 거뢁이가 돈 바퀴 수λ₯Ό a, 토끼가 돈 바퀴 수λ₯Ό b라고 ν•˜μž. cycle의 μ‹œμž‘μ λΆ€ν„° 토끼와 거뢁이가 cycleμ—μ„œ λ§Œλ‚œ μ§€μ κΉŒμ§€μ˜ 거리λ₯Ό k라고 ν•˜μž.
풀이 첫번째 λ‹¨κ³„μ—μ„œ λ‘˜μ΄ λ§Œλ‚˜κΈ°κΉŒμ§€ 거뢁이가 μ΄λ™ν•œ κ±°λ¦¬λŠ” m + a * n + k, 토끼가 μ΄λ™ν•œ κ±°λ¦¬λŠ” m + b * n + kκ°€ λœλ‹€. 토끼가 μ΄λ™ν•œ κ±°λ¦¬λŠ” 거뢁이가 μ΄λ™ν•œ 거리의 2λ°°κ°€ λ˜λ―€λ‘œ 2 * (m + a * n + k) = m + b * n + k κ°€ λœλ‹€. μ •λ¦¬ν•˜λ©΄ m = (b - 2a) * n - k κ°€ λœλ‹€. β€”β€”β€” 이제 λ‘λ²ˆμ§Έ λ‹¨κ³„μ—μ„œλŠ” κ±°λΆμ΄λŠ” κ·Έλž˜ν”„μ˜ μ‹œμž‘ μœ„μΉ˜(index 0)둜 μ΄λ™ν•œ μƒνƒœμ—μ„œ, ν† λΌλŠ” λ‘˜μ΄ λ§Œλ‚œ μœ„μΉ˜ (cycle의 μ‹œμž‘μ  κΈ°μ€€μœΌλ‘œ k) μ—μ„œ λ‘˜λ‹€ ν•œμΉΈμ”© μ›€μ§μ΄κ²Œ λœλ‹€. 거뢁이가 κ·Έλž˜ν”„μ˜ μ‹œμž‘ μœ„μΉ˜μ—μ„œ m 만큼 μ΄λ™ν•˜λ©΄ cycle의 μ‹œμž‘μ  0 에 λ„λ‹¬ν•œλ‹€. ν•œνŽΈ ν† λΌλŠ” cycle의 μ‹œμž‘μ μ„ κΈ°μ€€μœΌλ‘œ (k + m) % n μœ„μΉ˜μ— λ„λ‹¬ν•œλ‹€. (k + m) % n = (k + (b - 2a) * n - k) % n = ((b - 2a) * n) % n = 0 즉, 토끼도 cycle의 μ‹œμž‘μ μ— λ„λ‹¬ν•˜κ²Œ λœλ‹€.
  • μ‹œκ°„ λ³΅μž‘λ„λŠ” O(n) 인데 μ΄λŠ” ν’€μ΄μ—μ„œ 보이듯이 λ‘˜μ˜ 이동 거리 (array 쑰회 μ—°μ‚°μ˜ 수)κ°€ n에 λΉ„λ‘€ν•˜κΈ° λ•Œλ¬Έμ΄λ‹€.
class Solution { public: int findDuplicate(vector<int>& nums) { int start = nums[0]; int t = nums[start]; int h = nums[t]; while (t != h) { t = nums[t]; h = nums[nums[h]]; } t = start; while (t != h) { t = nums[t]; h = nums[h]; } return t; } };