动态规划定义
- 将一个复杂得问题 分解为简单得子问题
- 分治+最优子结构
- 动态规划和递归、分治, 没有本质得区别, 关键看有无最优得子结构
- 共性 找到重复得子问题 本质就是寻找重复性
- 差异性 动态规划有最优子结构, 中途可以提淘汰次优解
动态规划关键点
- 1最优子结构
- 2存储中间撞状态
- 3递推公式(dp 方程)
- Fib: opt[i] = opt[i-1] + opt[i-2]
- 二维路径: opt[i,j] = opt[i+1][j] +opt[i][j+1]
例题1 斐波那契数列
递归解法 O(n^2) 递归不是最优解
def fib(n):
if n <= 1:
return n
return fib(n-1) + fib(n-2)
可以添加缓存,例如lru cache 时间复杂度O(n)
memory = dict()
def fib(n):
if n <= 1:
return n
if memory.setdefault(n, 0) == 0:
memory[n] = fib(n - 1) + fib(n - 2)
return memory[n]
自底向上 从最下面开始 循环不断累积结果,时间复杂度O(n)
def fib2(n):
"""
自底向上得方法
return
"""
memory[0] = 0
memory[1] = 1
if n < 1:
return memory[n]
i = 0
while i <= n:
if memory.setdefault(n, 0) == 0:
memory[i] = memory[i-1] + memory[i-2]
i += 1
return memory[n]
例题2 路径计数
、
思路: 当前点的走法总和 = 右边点的走法总和 + 下面点的走法总和
递归代码模板
# Python
def recursion(level, param1, param2, ...):
# recursion terminator
if level > MAX_LEVEL:
process_result
return
# process logic in current level
process(level, data...)
# drill down
self.recursion(level + 1, p1, ...)
# reverse the current level status if needed
分治代码模板
# Python
def divide_conquer(problem, param1, param2, ...):
# recursion terminator
if problem is None:
print_result
return
# prepare data
data = prepare_data(problem)
subproblems = split_problem(problem, data)
# conquer subproblems
subresult1 = self.divide_conquer(subproblems[0], p1, ...)
subresult2 = self.divide_conquer(subproblems[1], p1, ...)
subresult3 = self.divide_conquer(subproblems[2], p1, ...)
…
# process and generate the final result
result = process_result(subresult1, subresult2, subresult3, …)
# revert the current level states