Алгоритмы с нуля
Dynamic programming: тест с множественным выбором
Шесть вопросов через весь юнит. Каждый отражает решение, которое вы принимаете в начале реальной DP-задачи — не определение для зубрёжки, а какое свойство проверить, какой state выбрать и какую сложность это даёт.
Убедитесь, что связываете два разрешающих свойства, два стиля реализации, дизайн state и классические рекуррентности — синтез, к которому вели отдельные уроки.
Задача распадается на подзадачи, и вы подтвердили, что эти подзадачи повторяются. Достаточно ли этого, чтобы оправдать DP-решение?
У вас есть рабочее решение через memoization (сверху вниз). Когда переписывание его в tabulation (снизу вверх) стоит усилий?
Для House Robber рекуррентность dp[i] = max(dp[i-1], dp[i-2] + nums[i]). Что кодирует каждая ветвь и почему хватает двух индексов истории?
0/1 knapsack работает за O(n*W). Почему это называют псевдополиномиальным, а не полиномиальным?
Алгоритм Longest Increasing Subsequence за O(n log n) хранит массив 'tails'. Что является ответом задачи и что на самом деле содержит массив tails?
Interval DP (matrix chain, burst balloons) идёт по возрастанию длины интервала и выбирает точку разбиения k внутри [i..j]. Почему обходить по длине, а не привычно слева направо по i?
Сквозная линия юнита — один чеклист перед написанием любой DP: подтвердить overlapping subproblems И optimal substructure; спроектировать наименьший state, схватывающий решение (один индекс для House Robber, два для knapsack и LCS, интервал для matrix chain); выбрать memoization или tabulation по глубине стека и памяти, а не по big-O; и знать, что реально лежит в таблице — включая массив tails в LIS, ответом служит его длина, а не содержимое. Сложность одинакова: число state на работу на один state.