数学归纳法
- 验证k0成立
- 证明如果ki成立,那么k(i+1)也成立
- 联合1和2,证明由 k0 -> kn 成立
求解方法
- 确定递推状态 💖
一个函数符号 f(x), 及这个函数的含义描述
一般函数所对应的值,就是要求解的值
- 确定递推公式
ki -> k(i+1)
- 分析边界条件
k0
- 程序实现
递归或者循环
例题
wallsize块墙,涂红、黄、蓝三种颜色,相邻两块墙不重色,另墙为环形,首尾不重色,求方案个数count
求解过程1
在不考虑首尾成环的情况下,第一块涂颜色0:
n 为wallsize,代表墙数;j 代表最后一块墙颜色
求解过程2
n为wallsize,代表墙数
考虑第1块和第n-1块墙颜色:
当两块颜色不一样时,第 n 块只有 1 种颜色方案,即第 n-1 块的颜色方案数,
当两块颜色一样时,第 n 块有 2 种颜色方案, 即第 n-2 块的颜色方案数乘 2,
动态规划
多了决策过程,递归算法中的最优解
状态转移公式重点
- 状态:一个数学符号、外加一个语义描述
- 决策:从所有可能产生最优解的状态中,选择最大值
- 阶段:本阶段只依赖于上一个阶段
列题:三角形最小路径和 (leetcode 120)
求解过程1
来向:从三角底部到顶部,根据下一层的值(还未求出)更新当前层的值
var minimumTotal = function(triangle) {
let n = triangle.length, dp = new Array(2)
for (let i=0;i<2;i++) {
dp[i] = new Array(n).fill(0)
}
for (let i=0;i<n;i++) {
let ind = (n-1) % 2
dp[ind][i] = triangle[n-1][i]
}
for (i = n-2;i>=0;i--) {
let ind = i % 2
let nextInd = 1 - ind
for (j = 0;j<=i;j++) {
dp[ind][j] = Math.min(dp[nextInd][j], dp[nextInd][j+1]) + triangle[i][j]
}
}
return dp[0][0]
};
求解过程2
去向:从三角顶部到底部,根据当前的值去更新下一层中受影响的值
var minimumTotal = function(triangle) {
let n = triangle.length, dp = new Array(n), ans = Number.MAX_SAFE_INTEGER
for (let i=0;i<n;i++) {
dp[i] = new Array(i+1).fill(Number.MAX_SAFE_INTEGER)
}
dp[0][0] = triangle[0][0]
for (let i=0;i<n-1;i++) {
for (let j=0;j<=i;j++) {
dp[i+1][j] = Math.min(dp[i][j] + triangle[i+1][j], dp[i+1][j])
dp[i+1][j+1] = Math.min(dp[i][j] + triangle[i+1][j+1], dp[i+1][j+1])
}
}
for (let i=0;i<dp[n-1].length;i++) ans = Math.min(ans, dp[n-1][i])
return ans
};