Coding Test/Codility

3. μ‹œκ°„ λ³΅μž‘λ„ (Time Complexity) Codility Lesson ν•œκ΅­μ–΄ 정리본 (JavaScript ver.)

chamroro 2025. 3. 1. 21:52

μ‹œκ°„ λ³΅μž‘λ„λž€?

μ‹œκ°„ λ³΅μž‘λ„(Time Complexity)λ₯Ό μ‚¬μš©ν•˜λ©΄ ν”„λ‘œκ·Έλž¨μ˜ μ‹€ν–‰ μ‹œκ°„μ„ λŒ€λž΅μ μœΌλ‘œ μΆ”μ •ν•  수 μžˆλ‹€. μ •ν™•ν•œ μ‹€ν–‰ μ‹œκ°„μ„ κ³„μ‚°ν•˜λŠ” 것은 컴파일러, μ»΄ν“¨ν„°μ˜ μ’…λ₯˜, ν”„λ‘œμ„Έμ„œ 속도 λ“± μ—¬λŸ¬ μš”μΈμ— μ˜ν•΄ 영ν–₯을 λ°›κΈ° λ•Œλ¬Έμ— 맀우 λ³΅μž‘ν•˜λ‹€. λ”°λΌμ„œ, μš°λ¦¬λŠ” μ‹€ν–‰ μ‹œκ°„μ˜ λŒ€λž΅μ μΈ 크기(order of magnitude) λ₯Ό μΈ‘μ •ν•˜λŠ” 것이 λͺ©ν‘œμ΄λ‹€.

λ³΅μž‘λ„λŠ” ν”„λ‘œκ·Έλž¨μ΄ μ‹€ν–‰ν•  수 μžˆλŠ” κΈ°λ³Έ μ—°μ‚°(primitive operation) 의 μ΅œλŒ€ 개수둜 λ³Ό 수 μžˆλ‹€. μ—¬κΈ°μ„œ κΈ°λ³Έ μ—°μ‚°μ΄λž€ λ§μ…ˆ, κ³±μ…ˆ, λŒ€μž… μ—°μ‚° 등을 μ˜λ―Έν•œλ‹€. ν•˜μ§€λ§Œ λͺ¨λ“  연산을 λ‹€ κ³ λ €ν•˜λŠ” λŒ€μ‹ , ν”„λ‘œκ·Έλž¨μ—μ„œ κ°€μž₯ 많이 μ‹€ν–‰λ˜λŠ” 지배적인 μ—°μ‚°(dominant operation) 에 μ΄ˆμ μ„ λ§žμΆ˜λ‹€.

ν”„λ‘œκ·Έλž¨μ˜ μ‹œκ°„ λ³΅μž‘λ„λŠ” μž…λ ₯ 데이터에 따라 달라지며, 보톡 μž…λ ₯ λ°μ΄ν„°μ˜ 크기에 μ˜ν•΄ κ²°μ •λœλ‹€. 예λ₯Ό λ“€μ–΄, μž…λ ₯이 𝑁 개의 μš”μ†Œλ₯Ό κ°€μ§„ 배열이라면, ν”„λ‘œκ·Έλž¨μ˜ μ‹€ν–‰ μ‹œκ°„μ€ 𝑁에 μ˜ν•΄ 쒌우될 것이닀.


1. 지배적인 μ—°μ‚°κ³Ό μ‹œκ°„ λ³΅μž‘λ„

λ‹€μŒ 예제λ₯Ό μ‚΄νŽ΄λ³΄μž.

예제: O(n) (μ„ ν˜• μ‹œκ°„ λ³΅μž‘λ„)

function dominant(n) {
    let result = 0;
    for (let i = 0; i < n; i++) {
        result += 1;
    }
    return result;
}

μœ„ μ½”λ“œμ—μ„œ result += 1; 연산이 n 번 μ‹€ν–‰λœλ‹€. λ”°λΌμ„œ 이 ν•¨μˆ˜μ˜ μ‹œκ°„ λ³΅μž‘λ„λŠ” O(n) (μ„ ν˜• μ‹œκ°„)이닀.

μ‹œκ°„ λ³΅μž‘λ„λ₯Ό λ‚˜νƒ€λ‚΄λŠ” Big-O ν‘œκΈ°λ²•μ—μ„œ μƒμˆ˜ κ³„μˆ˜(constant factor) λŠ” λ¬΄μ‹œλœλ‹€. 즉, 루프가 20 * n 번 μ‹€ν–‰λ˜λ“ , n / 5 번 μ‹€ν–‰λ˜λ“ , μ‹œκ°„ λ³΅μž‘λ„λŠ” μ—¬μ „νžˆ O(n)으둜 λ³Έλ‹€.


2. λ‹€μ–‘ν•œ μ‹œκ°„ λ³΅μž‘λ„ 비ꡐ

O(1) (μƒμˆ˜ μ‹œκ°„ λ³΅μž‘λ„)

function constant(n) {
    return n * n;
}

이 ν•¨μˆ˜λŠ” 항상 μΌμ •ν•œ 수의 연산을 μˆ˜ν–‰ν•˜λ―€λ‘œ O(1) (μƒμˆ˜ μ‹œκ°„)이닀.

O(log n) (둜그 μ‹œκ°„ λ³΅μž‘λ„)

function logarithmic(n) {
    let result = 0;
    while (n > 1) {
        n = Math.floor(n / 2);
        result += 1;
    }
    return result;
}

이 ν•¨μˆ˜λŠ” n을 반볡적으둜 2둜 λ‚˜λˆ„λ―€λ‘œ O(log n) (둜그 μ‹œκ°„)이닀.

O(n) (μ„ ν˜• μ‹œκ°„ λ³΅μž‘λ„)

function linear(n, A) {
    for (let i = 0; i < n; i++) {
        if (A[i] === 0) return 0;
    }
    return 1;
}

μ΅œμ•…μ˜ 경우 n 번 루프λ₯Ό μ‹€ν–‰ν•˜λ―€λ‘œ O(n) (μ„ ν˜• μ‹œκ°„)이닀.

O(n²) (이차 μ‹œκ°„ λ³΅μž‘λ„)

function quadratic(n) {
    let result = 0;
    for (let i = 0; i < n; i++) {
        for (let j = i; j < n; j++) {
            result += 1;
        }
    }
    return result;
}

이쀑 루프λ₯Ό μ‚¬μš©ν•˜μ—¬ O(n²) (이차 μ‹œκ°„) λ³΅μž‘λ„λ₯Ό κ°–λŠ”λ‹€.

O(n + m) (닀쀑 μ„ ν˜• μ‹œκ°„ λ³΅μž‘λ„)

function linear2(n, m) {
    let result = 0;
    for (let i = 0; i < n; i++) {
        result += i;
    }
    for (let j = 0; j < m; j++) {
        result += j;
    }
    return result;
}

μ—¬κΈ°μ„œλŠ” nκ³Ό m에 따라 독립적인 두 개의 루프가 μ‹€ν–‰λ˜λ―€λ‘œ O(n + m) 이닀.

O(2ⁿ) (μ§€μˆ˜ μ‹œκ°„ λ³΅μž‘λ„) 및 O(n!) (νŒ©ν† λ¦¬μ–Ό μ‹œκ°„ λ³΅μž‘λ„)

μ§€μˆ˜ μ‹œκ°„κ³Ό νŒ©ν† λ¦¬μ–Ό μ‹œκ°„ λ³΅μž‘λ„λ₯Ό κ°€μ§€λŠ” μ•Œκ³ λ¦¬μ¦˜μ€ μž…λ ₯ 크기가 쑰금만 컀져도 μ‹€ν–‰ μ‹œκ°„μ΄ κΈ‰κ²©νžˆ μ¦κ°€ν•˜λ―€λ‘œ, 일반적으둜 μ‚¬μš©λ˜μ§€ μ•ŠλŠ”λ‹€.


3. μ‹œκ°„ μ œν•œκ³Ό μ˜ˆμƒ λ³΅μž‘λ„

일반적으둜 평균적인 μ»΄ν“¨ν„°λŠ” 1초 μ•ˆμ— μ•½ 10⁸ 개의 연산을 μˆ˜ν–‰ν•  수 μžˆλ‹€. λ”°λΌμ„œ μž…λ ₯ 크기(𝑛)에 λ”°λ₯Έ μ˜ˆμƒ λ³΅μž‘λ„λ₯Ό λ‹€μŒκ³Ό 같이 μœ μΆ”ν•  수 μžˆλ‹€.

  • 𝑛 ≈ 1,000,000 → O(n) λ˜λŠ” O(n log n)
  • 𝑛 ≈ 10,000 → O(n²)
  • 𝑛 ≈ 500 → O(n³)

μ΄λŠ” λŒ€λž΅μ μΈ 기쀀이며, νŠΉμ • λ¬Έμ œμ— 따라 λ‹€λ₯Ό 수 μžˆλ‹€.


4. 곡간 λ³΅μž‘λ„ (Space Complexity)

곡간 λ³΅μž‘λ„λŠ” ν”„λ‘œκ·Έλž¨μ΄ 싀행될 λ•Œ ν•„μš”ν•œ λ©”λͺ¨λ¦¬ 크기λ₯Ό μ˜λ―Έν•œλ‹€.

  • O(1) (μƒμˆ˜ 곡간): κ³ μ •λœ 개수의 λ³€μˆ˜λ§Œ μ‚¬μš©ν•  λ•Œ
  • O(n) (μ„ ν˜• 곡간): μž…λ ₯ 크기 𝑛 에 λΉ„λ‘€ν•˜λŠ” 배열을 μ‚¬μš©ν•  λ•Œ
  • O(n²) (이차 곡간): 𝑛×𝑛 크기의 2차원 배열을 μ‚¬μš©ν•  λ•Œ

특히 μž¬κ·€(Recursion) λ₯Ό μ‚¬μš©ν•  경우, μŠ€νƒ λ©”λͺ¨λ¦¬κ°€ μΆ”κ°€μ μœΌλ‘œ ν•„μš”ν•˜κΈ° λ•Œλ¬Έμ— 곡간 λ³΅μž‘λ„λ₯Ό μ‹ μ€‘νžˆ κ³ λ €ν•΄μ•Ό ν•œλ‹€.


5. μ‹œκ°„ λ³΅μž‘λ„ 계산 예제

문제: 1λΆ€ν„° π‘›κΉŒμ§€μ˜ ν•© κ³„μ‚°ν•˜κΈ°

O(n²) (λΉ„νš¨μœ¨μ μΈ 방법)

function slowSum(n) {
    let result = 0;
    for (let i = 0; i < n; i++) {
        for (let j = 0; j <= i; j++) {
            result += 1;
        }
    }
    return result;
}

O(n) (μ„ ν˜• μ‹œκ°„)

function fastSum(n) {
    let result = 0;
    for (let i = 1; i <= n; i++) {
        result += i;
    }
    return result;
}

O(1) (μƒμˆ˜ μ‹œκ°„, μ΅œμ ν™”λœ 방법)

function optimizedSum(n) {
    return (n * (n + 1)) / 2;
}

이 방법은 단 ν•˜λ‚˜μ˜ μ—°μ‚°λ§Œ ν•„μš”ν•˜λ―€λ‘œ O(1) (μƒμˆ˜ μ‹œκ°„)이닀.

λ°˜μ‘ν˜•