μ‹œκ°„ λ³΅μž‘λ„
Β - Last update: 2023-06-02

μ‹œκ°„ λ³΅μž‘λ„ κ΄€λ ¨ 정리

μ£Όμš” μ‹œκ°„ λ³΅μž‘λ„

많이 μ“°μ΄λŠ” μ‹œκ°„ λ³΅μž‘λ„μ— λŒ€ν•œ 비ꡐ이닀. xμΆ• κΈ°μ€€μœΌλ‘œ λŒ€λž΅ 1000κΉŒμ§€μ˜ λ²”μœ„μ—μ„œ κ·Έλ¦° κ·Έλž˜ν”„μ΄λ‹€.

μ‹œκ°„ λ³΅μž‘λ„μ™€ μ‹€μ œ μˆ˜ν–‰ μ‹œκ°„

μœ„μ—μ„œ μ΄μ•ΌκΈ°ν•˜λŠ” O(n) / O(log n) λ”°μœ„μ˜ μ΄μ•ΌκΈ°λŠ” 많이 λ“€μ—ˆμ§€λ§Œ, κ·Έλž˜μ„œ μ‹€μ œλ‘œ μ–΄λ–»κ²Œ μ“°λŠ”μ§€μ— λŒ€ν•œ μ΄μ•ΌκΈ°λŠ” 많이 λΆ€λ”ͺν˜€λ³΄μ§€ μ•ŠμœΌλ©΄ 느끼기 μ–΄λ ΅λ‹€. λ‚΄κ°€ λŠλ‚€λŒ€λ‘œ 정리해본닀. λ‹Ήμ—°νžˆ μ ˆλŒ€μ μΈ 것은 μ•„λ‹ˆλ‹€.

μ»΄ν“¨ν„°μ˜ μ΄ˆλ‹Ή μ—°μ‚° 처리 λŠ₯λ ₯

μ‚¬λžŒλ§ˆλ‹€ 말이 λ§Žμ€λ°, λŒ€μΆ© 일반적인 μ‚¬μš©μž PC κΈ°μ€€ μ΄ˆλ‹Ή 1μ–΅ ~ 10μ–΅ 개의 μ—°μ‚° 정도λ₯Ό 처리 κ°€λŠ₯ν•˜λ‹¨ 것이 쀑둠이닀. λ¬Όλ‘  이것을 λ„ˆλ¬΄ 믿으면 μ•ˆλ˜λŠ”κ²Œ, 기본적으둜 연산은 μ‚¬λžŒμ΄ μ“΄ line λ‹¨μœ„κ°€ μ•„λ‹ˆλΌ μ–΄μ…ˆλΈ”λ¦¬ 레벨의 instruction레벨둜 λ΄μ•Όν•˜κΈ° λ•Œλ¬Έμ΄λ‹€ λ˜ν•œ, 이 instruction을 μ–΄μ…ˆλΈ”λ¦¬λ‘œ μ½”λ“œλ₯Ό λ³€ν™˜ν•΄μ„œ μ •ν™•νžˆ λͺ‡κ°œκ°€ μˆ˜ν–‰λ˜λŠ”μ§€ μ•ˆλ‹€κ³  해도, 각 instructionλ§ˆλ‹€μ˜ μˆ˜ν–‰μ‹œκ°„μ΄ λ™μΌν•˜μ§€ μ•ŠμœΌλ©°, CPUκ°€ prefetching도 ν•˜κ³ , branch prediction도 ν•˜κ³ , pipelining도 ν•˜κΈ° λ•Œλ¬Έμ—, λͺ¨λ“  μš”μ†Œλ₯Ό μ•ŒκΈ°λž€ μ–΄λ ΅λ‹€. μ •ν™•ν•œ μˆ˜ν–‰μ‹œκ°„μ΄λž€ 무쑰건 λΆ€λ”ͺν˜€λ΄μ•Ό μ•„λŠ” 것(λ˜ν•œ μ‹œν–‰μ‹œ 항상 κ°™μ§€ μ•Šλ‹€)이닀. ν•˜μ§€λ§Œ μΌλ°˜μ μœΌλ‘œλŠ” 보수적으둜 1얡을 κΈ°μ€€μ μœΌλ‘œ μž‘μ•„ ν’€κ³ , λ§Œμ•½ 이λ₯Ό 크게 λ„˜μ–΄κ°€μ§€λŠ” μ•Šμ„ κ²ƒμœΌλ‘œ(즉, 10μ–΅ 회 μ—°μ‚° 정도라면) μ˜ˆμƒλœλ‹€λ©΄ μƒμˆ˜μ΅œμ ν™”λ₯Ό μ‹œλ„ν•΄λ³΄λŠ” 것이 쒋을 것이닀.

N κ°’ κΈ°μ€€ ν—ˆμš©λ˜λŠ” μ‹œκ°„ λ³΅μž‘λ„

λ‚˜λŠ” N의 값에 따라 λŒ€λž΅ μ•„λž˜μ™€ 같은 기쀀을 μ“°κ³  μžˆλ‹€.

  • N <= 100: O(N^3), μ΅œμ ν™”λœ O(N^4) μ•Œκ³ λ¦¬μ¦˜μ„ 돌릴 수 μžˆλ‹€.
  • N <= 1,000: O(N^2), 주둜 DP둜 ν‘ΈλŠ” λ¬Έμ œμ—μ„œ 많이 μ‚¬μš©λ˜λŠ” λ²”μœ„μ΄λ‹€.
  • N <= 10,000: μ—¬κΈ°λΆ€ν„΄ λŒ€λž΅ O(N^2)도 timeout λ‚˜κΈ° 쉽닀. O(n log n) 정도가 ν—ˆμš©λœλ‹€κ³  λ΄μ•Όν•œλ‹€.
  • N <= 100,000: μ‹­λ§Œ λ‹¨μœ„λ₯Ό λ„˜μ–΄κ°€λ©΄ 슬슬 λΉ‘μ„Έλ‹€. O(N^2)λŠ” 무쑰건 timeout λ‚˜κΈ° μ‹œμž‘ν•˜λŠ” ꡬ간. O(n log n) 와 동등, ν˜Ήμ€ κ·Έ μ΄μƒμ˜ μ•Œκ³ λ¦¬μ¦˜μ„ μ‚¬μš©ν•΄μ•Ό ν•œλ‹€.
  • N <= 1,000,000: μ—¬κΈ°λΆ€ν„°λŠ” O(n)을 슬슬 μ¨μ•Όν•˜λŠ” λ‹¨μœ„μ΄λ‹€. O(n log n)도 슬슬 μ‹œκ°„μ΄ μ†Œμš”λ˜λŠ” 것이 λˆˆμ— λ“€μ–΄μ˜€κΈ° μ‹œμž‘ν•œλ‹€.
    • μΆ”κ°€μ μœΌλ‘œ μ•Œμ•„μ•Ό 것 쀑 ν•˜λ‚˜λŠ” 루트둜 μ€„μ΄λŠ” O(n^1/2), O(n * n^1/2) 기법도 자주 λ“±μž₯ν•˜λŠ” μ‹œμ μ΄λΌλŠ” 것이닀. κΌ­ μ•Œμ•„λ‘μž.
      • κ°€λ Ή μ†Œμˆ˜λ₯Ό νŒμ •ν•  λ•Œ 루트nκΉŒμ§€ 봐도 λœλ‹€λ˜μ§€ λ“±..
  • N >= 1,000,000,000: O(log n)이 κ°•μ œλœλ‹€. O(n^1/2)도 잘 짜면 λœλ‹€.

Master Theorem

λ§ˆμŠ€ν„° 정리 라고도 λΆˆλ¦¬λŠ” 이 이둠은 λ‹€μŒ μˆ˜μ‹μ„ μ˜λ―Έν•œλ‹€. μž¬κ·€ κ΄€κ³„μ‹μœΌλ‘œ ν‘œν˜„ν•œ μ•Œκ³ λ¦¬μ¦˜μ˜ μ‹œκ°„ λ³΅μž‘λ„λ₯Ό κ³„μ‚°ν•˜λŠ”λ°μ— 쓰인닀.

T(n)=aT(n/b)+f(n)T(n) = aT(n/b) + f(n)

μ—„λ°€νžˆλŠ” a(β‰₯1)a(\geq1)와 b(>1)b(>1)λŠ” μƒμˆ˜κ³ , f(n)f(n)은 점근적으둜 양인 ν•¨μˆ˜λΌκ³  ν•œλ‹€. nn은 문제 크기이닀. λΆ„ν•  μ •λ³΅μœΌλ‘œ 문제크기 nn인 λ¬Έμ œκ°€ n/bn/b인 aa개의 ν•˜μœ„ 문제둜 λ‚˜λ‰˜μ–΄μ§„λ‹€κ³  ν•˜λ©΄, aa개의 ν•˜μœ„ λ¬Έμ œλŠ” 각각 T(n/b)T(n/b) μ‹œκ°„μ— ν’€ 수 μžˆμ„ 것이닀. 이 λ•Œ, 문제λ₯Ό λ‚˜λˆ„κ³  각각의 κ²°κ³Όλ₯Ό ν•©μΉ˜λŠ”λ° λ“œλŠ” λΉ„μš©μ΄ f(n)f(n)이 λ˜λŠ” 것이닀.

이 λ•Œ, f(n)f(n)에 따라 μ•„λž˜μ²˜λŸΌ μ‹œκ°„ λ³΅μž‘λ„κ°€ κ³„μ‚°λœλ‹€.

  1. f(n)>nlogbaf(n) > n^{log_ba}: O(f(n))O(f(n))
  2. f(n)≃nlogbaf(n) \simeq n^{log_ba}: O(f(n)log⁑n)O(f(n)\log n)
  3. f(n)<nlogbaf(n) < n^{log_ba}: O(nlogba)O(n^{log_ba})

Binary Search의 μ‹œκ°„ λ³΅μž‘λ„ 생각해보기

μœ„ 이둠에 λ”°λ₯΄λ©΄, Binary Search의 μ‹œκ°„ λ³΅μž‘λ„λ₯Ό 계산해볼 수 μžˆλ‹€. μ•„λž˜μ²˜λŸΌ μž¬κ·€λ‘œ κ΅¬ν˜„ν•œλ‹€κ³  μƒκ°ν•΄λ³΄μž.

int bs(int s, int e, int t) {
int m = (s+e)>>1;
if (arr[m] == t) return m;
if (arr[m] > t) return bs(s,m-1);
else return bs(m+1,e);
}

이 경우, ν•¨μˆ˜μ— μ§„μž…ν•˜λ©΄ 1개의 ν•¨μˆ˜λ‘œ μͺΌκ°œμ§„λ‹€. 즉, a=1,b=1a=1, b=1인 κ²½μš°μ΄λ‹€. 이 경우 nlogba=n0=1n^{log_ba} = n^0 = 1이고, f(n)=1f(n) = 1μ΄λ―€λ‘œ, λ‘λ²ˆμ§Έ case에 ν•΄λ‹Ήν•œλ‹€. μ‹œκ°„ λ³΅μž‘λ„λŠ” O(f(n)log⁑n)=O(log⁑n)O(f(n)\log n) = O(\log n)이 λœλ‹€.

Merge sort의 μ‹œκ°„ λ³΅μž‘λ„ 생각해보기

이 κ²½μš°μ—λ„ λ§ˆμ°¬κ°€μ§€λ‘œ μž¬κ·€λ‘œ κ΅¬ν˜„λœλ‹€κ³  μƒκ°ν•΄λ³΄μž. λŒ€λž΅μ μΈ ν•¨μˆ˜λŠ” μ•„λž˜μ²˜λŸΌ λœλ‹€.

// [s, e]
void mergeSort(int s, int e) {
if (s >= e) return;
int m = (s+e)>>1;
mergeSort(s, m); mergeSort(m+1, e);
// μ΄ν•˜ μƒλž΅μ€ ν•©μΉ˜λŠ” κ³Όμ •... 전체 μ›μ†Œμ— λŒ€ν•΄μ„œ f(n) = O(n)이 κ±Έλ¦°λ‹€.
}

이 경우, ν•¨μˆ˜μ— μ§„μž…ν•˜λ©΄ 2개의 ν•¨μˆ˜λ‘œ μͺΌκ°œμ§„λ‹€. λ˜ν•œ, ꡬ간도 n/2n/2둜 쀄어든닀. 즉, a=2,b=2a=2, b=2인 κ²½μš°μ΄λ‹€. 이 경우, nlogba=n1=nn^{log_ba} = n^1 = n이고, f(n)=nf(n) = n이닀. 즉, λ‘λ²ˆμ§Έ case이닀. μ‹œκ°„ λ³΅μž‘λ„λŠ” O(f(n)log⁑n)=O(nlog⁑n)O(f(n)\log n) = O(n \log n)이 λ˜κ² λ‹€.

🏷️ 주제 λͺ©λ‘: