나누기와 정복 알고리즘과 동적 프로그래밍의 차이점


140

나누기와 정복 알고리즘과 동적 프로그래밍 알고리즘의 차이점은 무엇입니까? 두 용어는 어떻게 다릅니 까? 나는 그들 사이의 차이점을 이해하지 못한다.

이 두 가지의 차이점과 비슷한 근거를 설명하는 간단한 예를 들어보십시오.

답변:


156

나누고 정복

나누기와 정복은 문제를 하위 문제로 나누고 각 하위 문제를 재귀 적으로 정복하고 이러한 솔루션을 결합하여 작동합니다.

다이나믹 프로그래밍

동적 프로그래밍은 하위 문제가 겹치는 문제를 해결하는 기술입니다. 각 하위 문제는 한 번만 해결되며 각 하위 문제의 결과는 나중에 참조 할 수 있도록 테이블 (일반적으로 배열 또는 해시 테이블로 구현 됨)에 저장됩니다. 이러한 하위 솔루션은 원래 솔루션을 얻는 데 사용될 수 있으며 하위 문제 솔루션을 저장하는 기술은 메모라고합니다.

당신은 생각할 수 있습니다 DP = recursion + re-use

차이점을 이해하는 고전적인 예는 n 번째 피보나치 수를 얻기위한 두 가지 접근 방식을 모두 보는 것입니다. 이 자료 를 MIT에서 확인하십시오 .


나누고 정복 접근 나누고 정복 접근

다이나믹 프로그래밍 접근법 여기에 이미지 설명을 입력하십시오


9
이미지는 어떻게 만들었습니까? 마우스를 사용하여?
Vihaan Verma

34
이 전체 답변에서 가장 중요한 라인은 "중복 하위 문제"라고 생각합니다. DP는 그것을 가지고, 나누고 정복하지 않습니다
Hasan Iqbal

@HasanIqbalAnik 중복 하위 문제는 반복해서 발생하는 문제를 의미합니다. 위의 예에서 fn-2를 해결하는 것과 같습니다. 그래서 D & C에는 DP가 비효율적 인 이유가 있습니다.
Meena Chaudhary

1
이상한! '중복 하위 문제'는 문제에 대해 이야기하고 있지만 '동적 프로그래밍'은 일종의 알고리즘입니다. 나는 '문제'와 '알고리즘'을 구별하는 것이 중요하다고 생각합니다.
ZHU

그렇습니다. DP는 겹치는 부분을 기억하여 나누기와 정복보다 유리합니다.
imagineerThat

25

나누기와 정복과 동적 프로그래밍의 다른 차이점은 다음과 같습니다.

나누고 정복하십시오.

  1. 하위 문제에 대해 더 많은 작업을 수행하므로 더 많은 시간이 소비됩니다.
  2. 분할과 정복에서 하위 문제는 서로 독립적입니다.

다이나믹 프로그래밍 :

  1. 하위 문제를 한 번만 해결 한 다음 테이블에 저장합니다.
  2. 동적 프로그래밍에서 하위 문제는 독립적이지 않습니다.

분할 및 정복 알고리즘이 DP 대안보다 더 많은 작업을 수행 할 필요는 없습니다. 한 가지 예는 최대 산술 진행을 찾기위한 Erickson의 알고리즘입니다.
Michael Foukarakis 2016

17

때로는 반복적으로 프로그래밍 할 때 필요하지 않은 동일한 매개 변수를 가진 함수를 여러 번 호출합니다.

피보나치 숫자의 유명한 예 :

           index: 1,2,3,4,5,6...
Fibonacci number: 1,1,2,3,5,8...

function F(n) {
    if (n < 3)
        return 1
    else
        return F(n-1) + F(n-2)
}

F (5)를 실행 해 봅시다 :

F(5) = F(4) + F(3)
     = {F(3)+F(2)} + {F(2)+F(1)}
     = {[F(2)+F(1)]+1} + {1+1}
     = 1+1+1+1+1

1 번 F (4) 2 번 F (3) 3 번 F (2) 2 번 F (1)

동적 프로그래밍 방식 : 동일한 매개 변수를 가진 함수를 두 번 이상 호출하면 결과를 변수에 저장하여 다음에 직접 액세스하십시오. 반복적 인 방법 :

if (n==1 || n==2)
    return 1
else
    f1=1, f2=1
    for i=3 to n
         f = f1 + f2
         f1 = f2
         f2 = f

F (5)를 다시 호출 해 봅시다 :

fibo1 = 1
fibo2 = 1 
fibo3 = (fibo1 + fibo2) = 1 + 1 = 2
fibo4 = (fibo2 + fibo3) = 1 + 2 = 3
fibo5 = (fibo3 + fibo4) = 2 + 3 = 5

보시다시피, 다중 호출이 필요할 때마다 해당 변수에 액세스하여 값을 다시 계산하는 대신 값을 가져옵니다.

그런데 동적 프로그래밍이 재귀 코드를 반복 코드로 변환한다는 의미는 아닙니다. 재귀 코드를 원할 경우 하위 결과를 변수에 저장할 수도 있습니다. 이 경우이 기술을 메모라고합니다. 이 예에서는 다음과 같습니다.

// declare and initialize a dictionary
var dict = new Dictionary<int,int>();
for i=1 to n
    dict[i] = -1

function F(n) {
    if (n < 3)
        return 1
    else
    {
        if (dict[n] == -1)
            dict[n] = F(n-1) + F(n-2)

        return dict[n]                
    }
}

분할과 정복과의 관계는 D & D 알고리즘이 재귀에 의존한다는 것입니다. 그리고 일부 버전에서는 "같은 매개 변수 문제가있는 여러 함수 호출"이 있습니다. D & D 알고리즘의 T (n)을 개선하기 위해 DP가 필요한 예제에 대해서는 "매트릭스 체인 곱셈"과 "가장 긴 공통 서브 시퀀스"를 검색하십시오.


17

동적 프로그래밍과 나누기 및 정복의 유사점

내가 지금 보듯이 동적 프로그래밍은 나누기 및 정복 패러다임의 확장 이라고 말할 수있다 .

나는 그것들을 완전히 다른 것으로 취급하지 않을 것입니다. 둘 다 문제를 동일하거나 관련된 유형의 두 개 이상의 하위 문제로 재귀 적으로 분류하여 작동 하기 때문에 문제 가 직접 해결 될 정도로 단순해질 때까지 가능합니다. 그런 다음 하위 문제에 대한 솔루션을 결합하여 원래 문제에 대한 솔루션을 제공합니다.

그렇다면 왜 우리는 여전히 다른 패러다임 이름을 가지고 있으며 왜 동적 프로그래밍을 확장이라고 부릅니다. 문제가 특정 제한 사항이나 전제 조건이있는 경우에만 동적 프로그래밍 접근 방식이 문제점에 적용될 수 있기 때문 입니다. 그리고 그 후 다이내믹 프로그래밍은 메모 또는 테이블 기법 으로 분할 및 정복 방식을 확장 합니다.

단계별로 가자…

동적 프로그래밍 전제 조건 / 제한 사항

방금 살펴본 바와 같이 동적 프로그래밍을 적용하려면 문제를 나누고 정복해야하는 두 가지 주요 속성이 있습니다.

  • 최적의 하위 구조  — 하위 문제의 최적 솔루션으로 최적의 솔루션을 구축 할 수 있습니다

  • 하위 문제 겹침  — 문제가 여러 번 재사용되는 하위 문제로 분류되거나 문제에 대한 재귀 알고리즘이 항상 새로운 하위 문제를 생성하지 않고 동일한 하위 문제를 반복해서 해결합니다.

이 두 가지 조건이 충족되면이 분할 및 정복 문제는 동적 프로그래밍 방식을 사용하여 해결할 수 있다고 말할 수 있습니다.

나누기와 정복을위한 동적 프로그래밍 확장

동적 프로그래밍 접근 방식은 성능을 크게 향상시킬 수있는 하위 문제 솔루션을 저장하고 재사용 할 목적 으로 두 가지 기술 ( 메모테이블 )로 분할 및 정복 접근 방식을 확장 합니다. 예를 들어 피보나치 함수의 순진 재귀 구현은 O(2^n)DP 솔루션 이 시간 만으로 동일한 작업을 수행하는 경우 시간이 복잡 O(n)합니다.

메모 (하향식 캐시 채우기) 는 이전에 계산 된 결과를 캐싱하고 재사용하는 기술을 말합니다. 메모 된 fib함수는 다음과 같습니다.

memFib(n) {
    if (mem[n] is undefined)
        if (n < 2) result = n
        else result = memFib(n-2) + memFib(n-1)

        mem[n] = result
    return mem[n]
}

표 (하단 캐시 채우기) 는 비슷하지만 캐시 항목 채우기에 중점을 둡니다. 캐시의 값을 계산하는 것은 반복적으로 수행하는 것이 가장 쉽습니다. 의 표 버전 fib은 다음과 같습니다.

tabFib(n) {
    mem[0] = 0
    mem[1] = 1
    for i = 2...n
        mem[i] = mem[i-2] + mem[i-1]
    return mem[n]
}

메모 및 표 비교에 대한 자세한 내용은 여기를 참조하십시오 .

여기서 파악해야 할 주요 아이디어는 분할 및 정복 문제가 하위 문제와 겹치므로 하위 문제 솔루션의 캐싱이 가능해지면서 메모 / 표 작성이 현장으로 올라간다는 것입니다.

DP와 DC의 차이점

우리는 이제 DP 전제 조건과 그 방법론에 익숙해 졌으므로 위에서 언급 한 모든 것을 하나의 그림에 넣을 준비가되었습니다.

동적 프로그래밍 대 나누기 및 정복

코드 예제를 보려면 DP와 DC의 차이를 나타내는 이진 검색 및 최소 편집 거리 (Levenshtein Distance)라는 두 가지 알고리즘 예제를 찾을 수있는 여기 에서 더 자세한 설명 을 볼 수 있습니다.


1
주제 : 그래픽 태블릿을 사용하여 그렸습니까?
Geon George

1
@GeonGeorge 아니오, 그림은 펜으로 만든 다음 스캔
Oleksii Trekhleb

이것은 DP 조직에 관해 읽은 최고의 답변 중 하나입니다.
Ridhwaan Shakeel

8

나는 당신이 이미 Wikipedia와 다른 학술 자료를 읽었다 고 가정합니다. 그래서 나는 그 정보를 재활용하지 않을 것입니다. 나는 컴퓨터 공학 전문가가 아니라는 점에 유의해야하지만,이 주제에 대한 나의 이해에 대해 2 센트를 공유 할 것입니다 ...

다이나믹 프로그래밍

문제를 개별 하위 문제로 분류합니다. 피보나치 수열에 대한 재귀 알고리즘은 동적 프로그래밍의 한 예입니다. fib (n-1)을 먼저 해결하여 fib (n)을 해결하기 때문입니다. 원래 문제를 해결하기 위해 다른 문제를 해결합니다. 문제를 .

나누고 정복

이러한 알고리즘은 일반적으로 비슷한 문제를 해결 한 다음 마지막에 합칩니다. Mergesort는 나누기와 정복의 고전적인 예입니다. 이 예제와 피보나치 예제의 주요 차이점은 병합 소트에서 (이론적으로) 나눗셈이 임의적 일 수 있으며, 분할하는 방법에 관계없이 여전히 병합 및 정렬한다는 점입니다. 배열을 어떻게 나누 든 관계없이 배열을 병합하려면 동일한 양의 작업 을 수행해야합니다. fib (52)를 해결 하려면 fib (2)를 해결하는 것보다 많은 단계 가 필요합니다 .


5

나는 Divide & Conquer재귀 적 접근과 Dynamic Programming테이블 채우기로 생각 합니다.

예를 들어, Merge SortA는 Divide & Conquer각 단계에서, 당신은 전화를 반복적으로, 두 반으로 배열을 분할 알고리즘 Merge Sort두 부분에 다음 병합.

KnapsackA는 Dynamic Programming당신이 전체 배낭의 하위 문제에 대한 최적의 솔루션을 나타내는 테이블을 작성하는 등의 알고리즘입니다. 표의 각 항목은 항목 1-j가 주어진 무게의 봉지에 담을 수있는 최대 값에 해당합니다.


1
많은 경우에 해당되는 것이지만, 하위 문제의 결과를 테이블에 저장하는 것은 항상 사실이 아닙니다.
Gokul

2

나누기와 정복 에는 각 재귀 수준에서 세 단계가 포함됩니다.

  1. 문제를 하위 문제로 나누십시오 .
  2. 하위 문제를 재귀 적으로 해결하여 하위 문제를 극복하십시오 .
  3. 하위 문제점에 대한 솔루션을 원래 문제점에 대한 솔루션으로 결합 하십시오.
    • 그것은이다 하향식 접근 방식.
    • 하위 문제에 대해 더 많은 작업을 수행하므로 더 많은 시간이 소요됩니다.
    • 예. 피보나치 시리즈의 n 번째 항은 O (2 ^ n) 시간 복잡도로 계산 될 수 있습니다.

다이나믹 프로그래밍 은 다음 네 단계로 이루어집니다.

1. 최적 솔루션의 구조를 특성화 합니다.
2. 최적 솔루션의 값을 재귀 적으로 정의 하십시오.
3. 최적 솔루션의 가치를 계산 하십시오.
4. 구축 최적의 솔루션을 계산 정보로부터 .

  • 그것은이다 상향식 접근 방식.
  • 다시 계산하지 않고 이전에 계산 된 값을 사용하기 때문에 나누고 정복하는 것보다 시간이 덜 걸립니다.
  • 예. 피보나치 시리즈의 n 번째 항은 O (n) 시간 복잡도로 계산 될 수 있습니다.

이해하기 쉽도록 무차별 대입 솔루션으로 나누고 정복하고 동적 프로그래밍으로 최적화하는 것을 볼 수 있습니다. 하위 문제가 겹치는

NB 분할 및 정복 알고리즘은 dp로만 최적화 할 수 있습니다.


분할 및 정복은 상향식이고 동적 프로그래밍은 하향식
Bahgat Mashaly

0
  • 나누고 정복
    • 겹치지 않는 하위 문제가 발생했습니다.
    • 예 : 계승 수, 즉 fact (n) = n * fact (n-1)
fact(5) = 5* fact(4) = 5 * (4 * fact(3))= 5 * 4 * (3 *fact(2))= 5 * 4 * 3 * 2 * (fact(1))

위에서 볼 수 있듯이 팩토리얼에는 겹치지 않는 문제가 있으므로 팩트 (x)가 반복되지 않습니다.

  • 다이나믹 프로그래밍
    • 중복되는 하위 문제가 발생했습니다.
    • 예 : 피보나치 수, 즉 fib (n) = fib (n-1) + fib (n-2)
fib(5) = fib(4) + fib(3) = (fib(3)+fib(2)) + (fib(2)+fib(1))

위에서 볼 수 있듯이 fib (4)와 fib (3)는 모두 fib (2)를 사용합니다. 마찬가지로 많은 fib (x)가 반복됩니다. 이것이 피보나치가 하위 문제와 중복되는 이유입니다.

  • DP에서 하위 문제를 반복 한 결과 이러한 결과를 테이블에 유지하고 계산 노력을 절약 할 수 있습니다. 이것을 메모 라고합니다
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.