Разница между Divide и Conquer Algo и динамическим программированием
В чем разница между Divide and Conquer Algorithms
и Dynamic Programming Algorithms
? Как два термина отличаются друг от друга? Я не понимаю разницы между ними.
Пожалуйста, возьмите простой пример, чтобы объяснить любую разницу между ними и на каком основании они кажутся похожими.
Ответы
Ответ 1
Разделить и покорить
Разделите и покорите работы, разделив проблему на подзадачи, рекурсивно перехватите каждую подзадачу и объедините эти решения.
Динамическое программирование
Динамическое программирование - это метод решения проблем с перекрывающимися подзадачами. Каждая подзадача решается только один раз, и результат каждой подзадачи хранится в таблице (обычно реализуемой как массив или хеш-таблица) для будущих ссылок. Эти подрешения могут использоваться для получения исходного решения, а метод хранения решений подзадач известен как memoization.
Вы можете думать о DP = recursion + re-use
Классическим примером для понимания разницы было бы увидеть оба этих подхода к получению n-го числа фибоначчи. Отметьте этот материал из Массачусетского технологического института.
ИЗМЕНИТЬ
Разделить и победить подход
![Divide and Conquer approach]()
Подход к динамическому программированию
![enter image description here]()
Ответ 2
иногда, когда вы программируете рекурсивно, вы вызываете функцию с теми же параметрами несколько раз, что является ненужным.
Знаменитый пример чисел Фибоначчи:
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
Как вы можете видеть, всякий раз, когда вам нужен множественный вызов, вы просто получаете доступ к соответствующей переменной, чтобы получить значение вместо пересчета.
Кстати, динамическое программирование не означает конвертировать рекурсивный код в итеративный код. Вы также можете сохранить подзапросы в переменную, если вам нужен рекурсивный код. В этом случае метод называется memoization. Для нашего примера это выглядит так:
// 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]
}
}
Таким образом, отношение к Divide и Conquer заключается в том, что алгоритмы D & D основаны на рекурсии. И некоторые версии из них имеют этот "вызов с несколькими функциями с той же проблемой параметров". Найдите "умножение матричной цепочки" и "самую длинную общую подпоследовательность" для таких примеров, где DP необходим для улучшения T (n) D & D algo.
Ответ 3
Другим различием между делением и покорением и динамическим программированием может быть:
Разделить и победить:
- Работает ли над суб-проблемами и, следовательно, имеет больше времени.
- В разделе "Разделить" и "подчинить" подзадачи не зависят друг от друга.
Динамическое программирование:
- Решает проблемы только один раз, а затем сохраняет их в таблице.
- В динамическом программировании подзадача не является независимой.
Ответ 4
Я предполагаю, что вы уже прочитали Википедию и другие учебные ресурсы по этому вопросу, поэтому я не буду перерабатывать какую-либо информацию. Я также должен предупредить, что я не специалист по компьютерной науке, но я поделюсь своими двумя центами на мое понимание этих тем...
Динамическое программирование
Разбивает проблему на дискретные подзадачи. Рекурсивный алгоритм для последовательности Фибоначчи является примером динамического программирования, поскольку он решает для fib (n), сначала решая для fib (n-1). Чтобы решить исходную проблему, она решает другую проблему.
Разделить и покорить
Эти алгоритмы обычно решают подобные проблемы, а затем складывают их в конце. Mergesort - классический пример разделения и завоевания. Основное различие между этим примером и примером Фибоначчи заключается в том, что в объединенной системе разделение может (теоретически) быть произвольным, и независимо от того, как вы его разрезаете, вы все еще сходите и сортируете. Такой же объем работы должен быть выполнен для объединения массива, независимо от того, как вы его разделяете. Решение для fib (52) требует большего количества шагов, чем решение для fib (2).
Ответ 5
Я думаю о Divide & Conquer
как рекурсивный подход и Dynamic Programming
как заполнение таблицы.
Например, Merge Sort
является алгоритмом Divide & Conquer
, так как на каждом шаге вы разбиваете массив на две половины, рекурсивно вызываете Merge Sort
на две половины и затем объединяете их.
Knapsack
является алгоритмом Dynamic Programming
при заполнении таблицы, представляющей оптимальные решения для подзадач общего рюкзака. Каждая запись в таблице соответствует максимальному значению, которое вы можете носить в сумке с весом w с учетом предметов 1-j.