198. 打家劫舍

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

示例 1:

输入:[1,2,3,1]
输出:4
解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
偷窃到的最高金额 = 1 + 3 = 4 。
示例 2:

输入:[2,7,9,3,1]
输出:12
解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
偷窃到的最高金额 = 2 + 9 + 1 = 12 。

提示:

1 <= nums.length <= 100
0 <= nums[i] <= 400

// solve表示偷len个店,获得的收益
// 暴力搜索基本上都是递归
// 每次决策状态有两种,递归深度(有n层)--> O(2^n)
int solve(int len, int* nums) {
    if (len < 0) return 0;
    int mmax = max(nums[len] + solve(len - 2, nums), solve(len - 1, nums));
    return mmax;
}

如何优化,减少重复:记忆数组
// O(n)
int solve(int len, int* nums) {
    int result[len] = {0};
    if (len < 0) return 0;
    result[len] = max(nums[len] + solve(len - 2, nums), solve(len - 1, nums));
    return result[len];
}

动态规划的本质:递归
动态规划只能解决离散问题,离散问题容易设计状态
递归:原问题(N) -> 子问题(N - 1) -> 原问题(N)
最优子结构:

  1. 子问题最优决策可导出原问题最优决策
  2. 处理后效性 -> 无后效性

重叠子问题

  1. 去冗余
  2. 空间换时间

动态规划问题共性
套路: 最优,最大, 最小,最长,计数
离散问题: 容易设计状态(整数01背包问题)
最优子结构:N - 1可以推导N

动态规划四个基本步骤:

  1. 设计暴力算法,找到冗余
  2. 设计存储状态(一维,二维,三维数组,甚至用Map)
  3. 递归式(状态转移方程)
  4. 自顶向下上计算最优解编程方式:递归,倒着想
    自低向上上计算最优解编程方式:递推,用for
// 递归转为递推
int solve(int len, int* nums) {
    if (len == 0) return 0; // 为空
    int result[len] = {0};
    result[0] = nums[0]; // 当只有一家店
    result[1] = max(nums[0], nums[1]); // 当只有二家店
    if (len == 1) return result[0]; 
    for (int i = 2; i < len; i++) { // i = 2 边界
        result[i] = max(nums[i] + result[i - 2], result[i - 1]);
    }
    return result[len];
}
int fib(int n) {
    if (n <= 1) return 1;
    return fib(n - 1) + fib(n - 2);
}
// 转化为递推 
// 递推、递归时间复杂度一样的
int fib(int n) {
    f[0] = 0;
    f[1] = 1;
    f[2] = 1;
    for (int i = 3; i <= n; i++) f[i] = f[i - 1] + f[i - 2];
}

小兵向前冲
N * M的棋盘上,小兵要从左下角走到右上角,只能向上或者向右走,问有多少种走法

int f(int n, int m) {
    if (n == 0 || m == 0) return 0;
    if (n == 1 || m == 1) return 1;
    return f(n - 1, m) + f(n, m - 1);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值