Coding Test/Codility

4. μ›μ†Œ 개수 μ„ΈκΈ° (Counting Elements) Codility Lesson ν•œκ΅­μ–΄ 정리본 (JavaScript ver.)

chamroro 2025. 3. 1. 23:19

μ›μ†Œ 개수 μ„ΈκΈ°λž€?

배열을 ν™œμš©ν•˜μ—¬ 숫자 μ‹œν€€μŠ€λ₯Ό μ €μž₯ν•˜λŠ” λ°©λ²•μ—λŠ” μ—¬λŸ¬ κ°€μ§€κ°€ μžˆλ‹€. 일반적으둜 μ—°μ†λœ 숫자 aβ‚€, a₁, ..., aₙ₋₁λ₯Ό λ°°μ—΄μ˜ μΈλ±μŠ€μ— 맞좰 μ €μž₯ν•œλ‹€.

예λ₯Ό λ“€μ–΄:

let A = [4, 2, 4, 5];
// A[0] = 4, A[1] = 2, A[2] = 4, A[3] = 5

κ·ΈλŸ¬λ‚˜ μ›μ†Œλ₯Ό 직접 μ €μž₯ν•˜λŠ” λŒ€μ‹ , 각 숫자의 λ“±μž₯ 횟수λ₯Ό μ„ΈλŠ” λ°°μ—΄ 을 λ§Œλ“€ μˆ˜λ„ μžˆλ‹€.

이 경우, λ°°μ—΄ count[] λŠ” ν•΄λ‹Ή 값이 λ“±μž₯ν•œ 횟수λ₯Ό μ €μž₯ν•œλ‹€.

count[2] = 1; // 숫자 2λŠ” ν•œ 번 λ“±μž₯
count[4] = 2; // 숫자 4λŠ” 두 번 λ“±μž₯
count[5] = 1; // 숫자 5λŠ” ν•œ 번 λ“±μž₯

이 방법을 μ‚¬μš©ν•˜λ©΄ νŠΉμ • μˆ«μžκ°€ λ“±μž₯ν•œ 횟수λ₯Ό O(1) μ‹œκ°„μ— 확인할 수 μžˆλ‹€.


1. O(n + m) μ‹œκ°„ λ³΅μž‘λ„μ˜ μ›μ†Œ 개수 μ„ΈκΈ°

λ‹€μŒ ν•¨μˆ˜λŠ” λ°°μ—΄ A에 λ“±μž₯ν•˜λŠ” 각 숫자의 개수λ₯Ό μ„ΈλŠ” ν•¨μˆ˜μ΄λ‹€.

JavaScript μ½”λ“œ:

function counting(A, m) {
    let n = A.length;
    let count = new Array(m + 1).fill(0);
    for (let k = 0; k < n; k++) {
        count[A[k]] += 1;
    }
    return count;
}

이 ν•¨μˆ˜λŠ” O(n + m) μ‹œκ°„ λ³΅μž‘λ„λ₯Ό κ°€μ§„λ‹€. m 값이 λ„ˆλ¬΄ 크면 λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰μ΄ 증가할 수 μžˆλ‹€.


2. λ°°μ—΄ κ΅ν™˜μ„ ν†΅ν•œ ν•© 일치 μ—¬λΆ€ 확인

λ°°μ—΄ A와 Bκ°€ μ£Όμ–΄μ‘Œμ„ λ•Œ, ν•˜λ‚˜μ˜ μ›μ†Œλ₯Ό κ΅ν™˜ν•˜μ—¬ 두 λ°°μ—΄μ˜ 합을 λ™μΌν•˜κ²Œ λ§Œλ“€ 수 μžˆλŠ”μ§€ ν™•μΈν•˜λŠ” λ¬Έμ œμ΄λ‹€.

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

function slowSolution(A, B, m) {
    let n = A.length;
    let sumA = A.reduce((a, b) => a + b, 0);
    let sumB = B.reduce((a, b) => a + b, 0);
    
    for (let i = 0; i < n; i++) {
        for (let j = 0; j < n; j++) {
            let change = B[j] - A[i];
            sumA += change;
            sumB -= change;
            
            if (sumA === sumB) return true;
            
            sumA -= change;
            sumB += change;
        }
    }
    return false;
}

이 방법은 λͺ¨λ“  κ°€λŠ₯ν•œ μŒμ„ κ΅ν™˜ν•΄λ³΄λ―€λ‘œ O(n²) μ‹œκ°„μ΄ κ±Έλ¦°λ‹€.


O(n + m) (효율적인 방법)

μ’€ 더 효율적인 방법은 μ›μ†Œ 개수λ₯Ό μ„ΈλŠ” 배열을 ν™œμš©ν•˜λŠ” 것이닀.

function fastSolution(A, B, m) {
    let n = A.length;
    let sumA = A.reduce((a, b) => a + b, 0);
    let sumB = B.reduce((a, b) => a + b, 0);
    let d = sumB - sumA;
    
    if (d % 2 !== 0) return false;
    d /= 2;
    
    let count = counting(A, m);
    
    for (let i = 0; i < n; i++) {
        if (B[i] - d >= 0 && B[i] - d <= m && count[B[i] - d] > 0) {
            return true;
        }
    }
    return false;
}

이 방법은 O(n + m) μ‹œκ°„ λ³΅μž‘λ„λ₯Ό κ°€μ§€λ©°, 더 큰 μž…λ ₯ 값에도 효과적으둜 싀행될 수 μžˆλ‹€.

λ°˜μ‘ν˜•