leetcode解题:动态规划(上)

本文深入解析动态规划原理,包括递归+记忆化到递推的转换,状态定义,状态转移方程,及最优子结构概念。通过斐波那契数列和路径计数问题,阐述动态规划与回溯、贪心算法的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先讲一点:动态规划(Dynamic Programming)的名字有些言过其实,“Programming{Programming}Programming”的意思不是“编程”,这里指的是“递推”的意思,没有高瞻远瞩的意思,也没有计划未来什么事情的意思。
这里主要讲四点:

  • 递归+记忆化 -> 递推
  • 状态的定义:opt[n], dp[n], fib[n]{opt[n],\ dp[n], \ fib[n]}opt[n], dp[n], fib[n]
  • 状态转移方程:opt[n]=best_of(opt[n−1], opt[n−2], ...){opt[n]=best\_of (opt[n-1], \ opt[n-2],\ ...)}opt[n]=best_of(opt[n1], opt[n2], ...)
  • 最优子结构
例子:斐波那契数列

0, 1, 1, 2, 3, 5, 8, 13, 21, ...{0,\ 1,\ 1,\ 2,\ 3,\ 5,\ 8,\ 13,\ 21,\ ...}0, 1, 1, 2, 3, 5, 8, 13, 21, ...
递推公式:F[n]=F[n−1]+F[n−2]{F[n]=F[n-1]+F[n-2]}F[n]=F[n1]+F[n2]
DP
先看上面这张图的左上角是斐波那契数列的递推公式;右上角是代码,不过这个代码写的并不简洁,可以改写为:

def fib(n):
	return n if n <= 1 else fib(n-1)+fib(n-2)

上面是斐波那契数列最普通的递归算法。递归加上记忆化 就是递推,看下图:
DP2
这幅图跟第一个图的区别在哪儿?区别在右上角的代码部分,其中增加了“记忆代码(即,memo数组)”,求解顺序也就变了,变成从下往上推(从fib(0)往上推fib(6))。
所以说:递归+记忆化 ==》递推;递推公式:F[n]=F[n−1]+F[n−2]{F[n]=F[n-1]+F[n-2]}F[n]=F[n1]+F[n2]

例子:COUNT THE PATHS

paths_count
从开始位置到结束位置,小人只能往右或往下走,遇到石头不能走,问一共有多少种走法。
countPaths
递归的思路是从开始位置走,一直到结束位置。
递推的思路是从结束位置开始,走到开始位置。
看下面递推的走法:

它的状态转移方程:

opt[i, j] = opt[i-1, j] + opt[i, j-1]
======================================
if a[i, j] == '空地':
	opt[i, j] = opt[i-1, j] + opt[i, j-1]
else: // 石头
	opt[i, j] = 0

从结束位置开始往上递推,就有了下面这幅图,方格子里面的数字就是“记忆体”,表示从当前位置到结束位置的走法总数,特别注意数字指的是一共有多少种走法。
paths
不要从开始位置走,很容易回溯(递归),越走越迷糊。(坚信递推公式是正确的)
看一下递推的时间复杂度:O(m∗n){O(m*n)}O(mn)
总结:

  • 一定要递推!!(尽量不要用递归+记忆化的方式)
  • 状态的定义:opt[n],dp[n],fib[n]{opt[n],dp[n],fib[n]}opt[n]dp[n]fib[n]。斐波那契数列的状态定义为一维数组fib[n]){fib[n])}fib[n]),count the paths的状态定义为二维数组opt[i,j]{opt[i, j]}opt[i,j]
  • 状态转移方程:opt[n]=best_of(opt[n−1], opt[n−2], ...){opt[n]=best\_of (opt[n-1], \ opt[n-2],\ ...)}opt[n]=best_of(opt[n1], opt[n2], ...)
  • 最优子结构:当前状态取决于前一个状态,和之后的更多过去状态都无关。
DP vs 回溯 vs 贪心
  • 回溯(递归)-重复计算
  • 贪心-永远局部最优
  • DP-记录局部最优子结构/多种记录值,集前两者之大成。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值