[perl] 동적 계획법과 분할 정복

본 포스트에서는 동적 계획법과 분할 정복이라는 두 가지 알고리즘 기법에 대해 알아보겠습니다. 두 가지 기법은 각각의 고유한 방식으로 문제를 해결하며, 특정 유형의 문제에 중요한 역할을 합니다.

동적 계획법(Dynamic Programming)

동적 계획법은 큰 문제를 해결하기 위해 부분 문제로 분해하고, 작은 부분 문제들의 해를 이용하여 큰 문제의 해를 구하는 방법입니다. 작은 문제들의 해를 저장하고, 이를 이용하여 더 큰 문제들을 해결합니다.

동적 계획법은 중복되는 부분 문제들을 효율적으로 해결하여 계산 복잡도를 줄이는 데에 중점을 둡니다. 주로 최적화 문제나 결정 문제를 해결하는 데에 사용됩니다. 동적 계획법은 피보나치 수열이나 그리드 알고리즘 등 다양한 문제에 적용될 수 있습니다.

Perl에서는 동적 계획법을 구현하고자 할 때 Memoization(메모이제이션) 기법을 활용하는 경우가 많습니다. Memoization은 계산한 값을 배열에 저장하여 재활용하는 기법으로, 같은 계산을 반복하지 않고 효율적으로 동일한 값을 참조할 수 있도록 돕습니다.

예시

my @memo;

sub fibonacci {
    my $n = shift;
    return $n if $n <= 1;
    return $memo[$n] if defined $memo[$n];
    $memo[$n] = fibonacci($n-1) + fibonacci($n-2);
    return $memo[$n];
}

print fibonacci(10);

분할 정복(Divide and Conquer)

분할 정복은 큰 문제를 더 작은 문제로 분할하여 각각을 해결한 후, 그 결과를 합쳐서 전체 문제의 해를 구하는 알고리즘 기법입니다. 재귀적인 구조를 가지며, 주로 이진 탐색, 합병 정렬, 퀵 정렬 등의 정렬 알고리즘에서 사용됩니다.

분할 정복은 문제를 더 작은 부분으로 나누어 처리할 수 있을 때 유용하며, 각 부분 문제는 별개로 해결될 수 있어야 합니다. 또한, 각 부분 문제의 해결이 서로 영향을 미치지 않아야 합니다.

예시

sub binary_search {
    my ($arr, $low, $high, $target) = @_;
    
    if ($high >= $low) {
        my $mid = $low + int(($high - $low) / 2);
        
        if ($arr->[$mid] == $target) {
            return $mid;
        }
        
        if ($arr->[$mid] > $target) {
            return binary_search($arr, $low, $mid-1, $target);
        } else {
            return binary_search($arr, $mid+1, $high, $target);
        }
    }
    return -1;
}

my @arr = (1, 3, 5, 7, 9);
my $target = 5;
my $result = binary_search(\@arr, 0, scalar(@arr)-1, $target);
print "Element is present at index $result" if $result >= 0;

동적 계획법과 분할 정복은 각각의 특성에 맞게 적합한 문제를 해결하는 데에 유용하며, 프로그래밍 언어에 따라 다양한 구현 방식이 있을 수 있습니다. 프로그래머가 알맞은 상황에 적절한 알고리즘을 선택하여 문제를 해결하는 데에 도움이 됩니다.

참고문헌: GeeksforGeeks