본문 바로가기

JAVA/알고리즘

[알고리즘] 재귀와 메모이제이션

728x90

1. 소개

재귀와 메모이제이션은 알고리즘 설계와 프로그래밍에서 매우 중요한 개념입니다. 이 글에서는 재귀의 기본 개념과 그것이 가지는 한계를 설명하고, 메모이제이션을 통해 재귀의 성능을 어떻게 향상시킬 수 있는지 알아보겠습니다.

 

2. 재귀(Recursion)

재귀는 함수가 자기 자신을 호출하는 프로그래밍 기법입니다. 주로 복잡한 문제를 더 작은 하위 문제로 분할하여 해결할 때 유용합니다.

 

재귀 함수의 기본 구조

function factorial(n) {
    if (n === 0) {
        return 1;
    } else {
        return n * factorial(n - 1);
    }
}
console.log(factorial(5)); // 120

위 코드에서 factorial 함수는 자기 자신을 호출하며 팩토리얼 값을 계산합니다.

 

3. 재귀의 문제점

재귀는 효율적일 수 있지만, 중복 계산으로 인해 성능 저하가 발생할 수 있습니다. 예를 들어, 피보나치 수열을 재귀로 계산할 때 동일한 계산이 반복적으로 수행됩니다.

 

4. 메모이제이션(Memoization)

메모이제이션은 이미 계산한 결과를 저장하여 동일한 계산을 반복하지 않도록 하는 기술입니다. 이를 통해 재귀 함수의 성능을 크게 향상시킬 수 있습니다.

 

피보나치 수열 계산 예제

function fibonacci(n, memo = {}) {
    if (n in memo) {
        return memo[n];
    }
    if (n <= 1) {
        return n;
    }
    memo[n] = fibonacci(n - 1, memo) + fibonacci(n - 2, memo);
    return memo[n];
}
console.log(fibonacci(10)); // 55

위 코드에서 memo 객체를 사용하여 이미 계산된 값을 저장하고, 필요할 때마다 이를 참조합니다.

 

5. 재귀와 메모이제이션의 결합

재귀와 메모이제이션을 결합하면 성능을 크게 개선할 수 있습니다. 위의 피보나치 수열 예제를 통해 이를 확인할 수 있습니다.

메모이제이션을 사용하지 않은 경우와 사용한 경우의 성능 차이를 코드와 함께 설명합니다.

 

메모이제이션을 사용하지 않은 피보나치 수열

function fibonacci(n) {
    if (n <= 1) {
        return n;
    }
    return fibonacci(n - 1) + fibonacci(n - 2);
}
console.log(fibonacci(10)); // 55 (but much slower for large n)

 

6. 실제 사례와 응용

재귀와 메모이제이션은 다양한 알고리즘에서 사용됩니다. 예를 들어, 동적 계획법(Dynamic Programming)에서 두 기법은 핵심적인 역할을 합니다.

실생활 응용 예시

  • 최단 경로 문제
  • 문자열 매칭
  • 게임 이론

 

7. 결론

재귀와 메모이제이션은 복잡한 문제를 해결하는 강력한 도구입니다. 이 글에서 다룬 개념과 예제를 통해 두 기법의 중요성과 유용성을 이해할 수 있었기를 바랍니다. 더 나아가 동적 계획법 등 고급 알고리즘으로 학습을 확장해보세요.