动态规划是什么?
动态规划是算法设计中的一种方法。
它将一个问题分解为相互重叠的子问题,通过反复求解子问题。来解决原来的问题。
注意:分而治之强调是分解为相互独立的子问题。
斐波那契数列
定义子问题:F(n) = F(n-1) + F(n-2)
反复执行:从2循环到n,执行上述公式
应用一:爬楼梯(力扣70)
解题思路:
- 爬到第n阶可以在第n-1阶爬1个台阶,或者在第n-2阶爬2个台阶
- F(n) = F(n-1) + F(n-2)
- 使用动态规划
/**
* @param {number} n
* @return {number}
*/
var climbStairs = function(n) {
if(n < 2) {
return 1;
}
let dp0 = 1;
let dp1 = 1;
for(let i= 2; i <= n; i++){
let temp = dp0;
dp0 = dp1;
dp1 = dp0 + temp;
}
return dp1;
};
var climbStairs2 = function(n) {
if(n < 2) {
return 1;
}
let dp = [1, 1];
for(let i= 2; i <= n; i++){
dp[i] = dp[i-1] + dp[i-2];
}
return dp[n];
};
应用二:打家劫舍(力扣198,213)
解题思路:
- f(k)=从前k个房间中能偷窃到的最大数额
- Ak=第k个房屋的钱数
- f(k)=max(f(k-2)+ Ak, f(k-1))
/**
* @param {number[]} nums
* @return {number}
*/
var rob = function(nums) {
if(nums.length == 1){
return nums[0];
}
if(nums.length == 0){
return 0;
}
let dp0 = 0;
let dp1= nums[0];
for(let i=2; i <= nums.length; i++){
const dp2 = Math.max(dp0 + nums[i-1], dp1);
dp0 = dp1;
dp1 = dp2;
}
return dp1;
};
var rob2 = function(nums) {
if(nums.length == 1){
return nums[0];
}
if(nums.length == 0){
return 0;
}
let dp = [0, nums[0]];
for(let i=2; i <= nums.length; i++){
dp[i] = Math.max(dp[i-2]+ nums[i-1], dp[i-1]);
}
return dp[nums.length];
};
213,环形房屋
/**
* @param {number[]} nums
* @return {number}
*/
var rob = function(nums) {
if(nums.length == 0){
return 0;
}
if(nums.length == 1){
return nums[0];
}
//不偷最后一家
let res1 = rawRob(nums.slice(0, nums.length - 1));
let res2 = rawRob(nums.slice(1));
return Math.max(res1, res2);
};
function rawRob(nums){
let dp0 = 0;
let dp1 = nums[0];
for(let i = 2; i <= nums.length; i++){
const dp2 = Math.max(dp0 + nums[i-1], dp1);
dp0 = dp1;
dp1 = dp2;
}
return dp1;
}