动态规划
是什么
它将一个问题分解为相互重叠
的子问题,能过反复求解子问题,来解决原来的问题
与分而治之的区别
子问题是否重叠
demo:翻转树 vs 斐波哪契数列
翻转树: 拆天2棵树,左右树再翻转,是不样的的操作
斐波哪契数列: fn(n)= fn(n-1)+fn(n-2),适用于所有子问题
leetcode
斐波哪契数列
// function test(n){
// if(n <=1){
// return 1;
// }
// return test(n) = test(n-1)+test(n-2)
// }
function test(n){
if(n ==0){
return 0;
}
if(n ==1){
return 1
}
return test(n-1)+test(n-2)
}
var result = test(3)
console.log('result',result);
70 爬楼梯
思路
- 假设要爬到第n级楼梯,哪么倒退一步有2种方案, 第n-1级楼梯+1,第n-2级楼梯+2
- 首先考虑第一步的走法:第一步可以走1级台阶,也可以走2级台阶。那么,设S(n)表示走n级台阶的走法数量,如果第一步走1级台阶,剩下的台阶数为n-1,也就是说这种情况下的走法是相当于S(n-1);同理,如果第一步走2级台阶,剩下的台阶数为n-2,这样的走法相当于S(n-2)
代码
基础版
if (n < 2) {
return 1
}
const db = [1,1]
for (let i = 2; i <= n; i++) {
db[i] = db[i-1] + db[i-2]
}
console.log(db);
return db[db.length-1]
优化,缓存版
var climbStairs = function(n) {
if (n < 2) {
return 1
}
let db0 = 1;
let db1 = 1;
for (let i = 2; i <= n; i++) {
const temp = db0;
db0 = db1;
db1 = db1 + temp;
}
console.log(db1);
return db1
};
198 打家劫舍
思路
- 求出特殊情况(nums.length === 0,nums.length === 0)
- 除了特殊情况外的通用公式
dp[i] = Math.max(nums[i]+dp[i-2],dp[i-1])
322 零钱兑换
题目
给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 - 1。
你可以认为每种硬币的数量是无限的。
输入: var coins = [1, 2, 5], amount = 11
输出: 3
解释: 11 = 5 + 5 + 1
思路
我们经常听到「最优子结构」「缩小问题规模」「自顶向下」「自底向上」等跟动态规划相关的词汇
这里我们使用「自顶向下」思想来考虑这个题目
- 假设给出的不同面额的硬币是[1, 2, 5],目标是 120,问最少需要的硬币个数?
- 我们要分解子问题,分层级找最优子结构,看到这又要晕了哈,憋急~~ 下面马上举例。
- 这里我们使用「自顶向下」思想来考虑这个题目,然后用「自底向上」的方法来解题,
体验算法的冰火两重天。 - dp[i]: 表示总金额为 i 的时候最优解法的硬币数
我们想一下:求总金额 120 有几种方法?下面这个思路关键了 !!!
一共有 3 种方式,因为我们有 3 种不同面值的硬币。- 拿一枚面值为 1 的硬币 + 总金额为 119 的最优解法的硬币数量
这里我们只需要假设总金额为 119 的最优解法的硬币数有人已经帮我们算好了,
不需要纠结于此。(虽然一会也是我们自己算,哈哈)
即:dp[119] + 1 - 拿一枚面值为 2 的硬币 + 总金额为 118 的最优解法的硬币数
这里我们只需要假设总金额为 118 的最优解法的硬币数有人已经帮我们算好了
即:dp[118] + 1 - 拿一枚面值为 5 的硬币 + 总金额为 115 的最优解法的硬币数
这里我们只需要假设总金额为 115 的最优解法的硬币数有人已经帮我们算好了
即:dp[115] + 1
- 所以,总金额为 120 的最优解法就是上面这三种解法中最优的一种,也就是硬币数最少
的一种,我们下面试着用代码来表示一下: - dp[120] = Math.min(dp[119] + 1, dp[118] + 1, dp[115] + 1);
- 推导出「状态转移方程」:
dp[i] = Math.min(dp[i - coin] + 1, dp[i - coin] + 1, ...)
其中 coin 有多少种可能,我们就需要比较多少次,那么我们到底需要比较多少次呢?
当然是 coins 数组中有几种不同面值的硬币,就是多少次了~ 遍历 coins 数组,
分别去对比即可 - 上面方程中的 dp[119],dp[118],dp[115] 我们继续用这种思想去分解,
这就是动态规划了,把这种思想,思考问题的方式理解了,这一类型的题目
问题都不会太大。 -->
- 拿一枚面值为 1 的硬币 + 总金额为 119 的最优解法的硬币数量
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。