1, 1, 2, 3, 5, 8, 13 ...
复制代码
抽象成表达式, n >= 2, 第 n 个数等于 始终有F(n) = F(n - 1) + F(n - 2)web
定义子问题算法
F(n) = F(n - 1) + F(n - 2)
复制代码
反复执行子问题数组
从2循环到n, 执行子问题
复制代码
经过两道LeetCode算法题,来了解一下吧markdown
题目描述:app
假设你正在爬楼梯。须要 n 阶你才能到达楼顶。
每次你能够爬 1 或 2 个台阶。你有多少种不一样的方法能够爬到楼顶呢?
注意:给定 n 是一个正整数。
复制代码
解题思路ui
例如n=3时,爬到第3阶的方法 就等于 爬到第2阶的方法 加上 爬到第一阶的方法,即 2 + 1
复制代码
var climbStairs = function(n) {
if (n < 2) return 1
// 这里设计db的下标 恰好 与第几阶 对应,这样取第n阶的方法就是 db[n]
let db = [1, 1, 2] // 下标为2,就是须要2步
for (let i = 2; i <= n; i ++) {
db[i] = db[i - 1] + db[i - 2]
}
return db[n] // db --> [1, 1, 2, 3, 5]
};
时间复杂度: O(n)
空间复杂度: O(n)
复制代码
var climbStairs = function(n) {
if (n < 2) return 1
let dp0 = 1; // 用来表示第0阶的方法
let dp1 = 1; // 用来表示第1阶的方法
for (let i = 2; i <= n; i ++) {
const temp = dp0
dp0 = dp1 // 不断的让dp0表明倒数第二个数字
dp1 = dp1 + temp 不断的让dp1表明倒数的第一个数字,倒数第一个数字等于前两位之和
}
return dp1
};
时间复杂度: O(n)
空间复杂度: O(1)
复制代码
题目描述:spa
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有必定的现金,
影响你偷窃的惟一制约因素就是相邻的房屋装有相互连通的防盗系统,
若是两间相邻的房屋在同一夜被小偷闯入,系统会自动报警。
给定一个表明每一个房屋存放金额的非负整数数组,
计算你 不触动警报装置的状况下 ,一晚上以内可以偷窃到的最高金额。
通俗一点就是:不能连续偷相邻的房间
复制代码
--设计
示例一:
输入:[1,2,3,1]
输出:4
解释:偷窃 1 号房屋 (金额 = 1) ,而后偷窃 3 号房屋 (金额 = 3)。
偷窃到的最高金额 = 1 + 3 = 4 。
示例二:
输入:[2,7,9,3,1]
输出:12
解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
偷窃到的最高金额 = 2 + 9 + 1 = 12 。
复制代码
- F(k) = 从前 k 个房屋中能偷窃盗的最大数额
- A(k) = 第 k 个房屋的钱数
- F(k) = max( F(k - 2) + A(k), F(k - 1) )
复制代码
输入: [1, 2, 3,1]
输出:4
1. k = 1, 只有一个房间, 最大金额就是F(1) = 1
2. k = 2, 有两个房间,最大金额就是 Math.max( F(1), F(2) )
3. k = 3, 有三个房间,最大金额就是 Math.max( F(1) + F(3), F(2) )
4. k = 4, 有四个房间,最大金额就是 前两个房间金额的最大值,加上第四个,
与 前三个房屋金额的最大值 作比较, 取较大的值
即Math.max( F(2) + A(4), F(3) )
能够得出 F(k)的公式
F(k) = max( F(k - 2) + A(k), F(k - 1) )
复制代码
var rob = function(nums) {
const length = nums.length
if (length === 0) return 0
// 这里设计dp的下标 表示 第几个房屋
// 下标为0,就是前0个房屋打劫到的最大金额为0;下标为1,就是前1个房屋打劫到的最大金额为nums[0]
const dp = [0, nums[0]]
for (let i = 2; i <= length; i ++) {
//子问题的通项公式:F(k) = max( F(k - 2) + A(k), F(k - 1) )
dp[i] = Math.max(dp[i - 2] + nums[i - 1], dp[i - 1])
}
return dp[length]
};
时间复杂度:O(n)
空间复杂度:O(n)
复制代码
var rob = function(nums) {
const length = nums.length
if (length === 0) return 0
let dp0 = 0
let dp1 = nums[0] // 前一个房屋能打劫到的最大金额
for (let i = 2; i <= length; i ++) {
const dp2 = Math.max( dp0 + nums[i - 1], dp1 )
dp0 = dp1
dp1 = dp2
}
return dp1
};
时间复杂度: O(n)
空间复杂度: O(1)
复制代码
动态规划是经过反复求解子问题来解决原来的问题,即F(n)的通项公式,
再把一些特殊状况处理一下便可,如:n = 0, n = 1时。
复制代码