打家劫舍(LeetCode 198)

简介: 打家劫舍(LeetCode 198)

打家劫舍(LeetCode 198)

Description

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

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

Sample Input 1

[1,2,3,1]

Sample Output 1

4

Sample Tips 1

偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
偷窃到的最高金额 = 1 + 3 = 4 。

Sample Input 2

[2,7,9,3,1]

Sample Output 2

true

Sample Tips 2

偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
偷窃到的最高金额 = 2 + 9 + 1 = 12 。

Tips

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

算法思想:

前房屋偷与不偷取决于前一个房屋和前两个房屋是否被偷了。

所以这里就更感觉到,当前状态和前面状态会有一种依赖关系,那么这种依赖关系都是动规的递推公式。

当然以上是大概思路,打家劫舍是dp解决的经典问题,

动规五部曲分析如下:

  1. 确定dp数组以及下标的含义

    dp[i]:考虑下标i(包括i)以内的房屋,最多可以偷窃的金额为dp[i]

  2. 确定递推公式

    决定dp[i]的因素就是第i房间偷还是不偷。

    如果偷第i房间,那么dp[i] = dp[i - 2] + nums[i] ,即:第i-1房一定是不考虑的,找出 下标i-2(包括i-2)以内的房屋,最多可以偷窃的金额为dp[i-2] 加上第i房间偷到的钱。

    如果不偷第i房间,那么dp[i] = dp[i - 1],即考 虑i-1房,(注意这里是考虑,并不是一定要偷i-1房,这是很多同学容易混淆的点

    然后dp[i]取最大值,即dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);

  3. dp数组如何初始化

    从递推公式dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);可以看出,递推公式的基础就是dp[0] 和 dp[1]

    从dp[i]的定义上来讲,dp[0] 一定是 nums[0],dp[1]就是nums[0]和nums[1]的最大值即:dp[1] = max(nums[0], nums[1]);

    vector<int> dp(nums.size());
    dp[0] = nums[0];
    dp[1] = max(nums[0], nums[1]);
  4. 确定遍历顺序

    dp[i] 是根据dp[i - 2] 和 dp[i - 1] 推导出来的,那么一定是从前到后遍历!

    for (int i = 2; i < nums.size(); i++) {
        dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);
    }
  5. 推导dp数组

    输入 [2,7,9,3,1]

    dp数组状态图为:

    i:  0  1  2  3  4
    dp: 2  7 11 11 12

    dp[nums.size() - 1]为结果。 (12)

综上分析完毕,代码如下:

class Solution {
public:
    int rob(vector<int>& nums) {
        if (nums.size() == 0) return 0;
        if (nums.size() == 1) return nums[0];
        vector<int> dp(nums.size());
        dp[0] = nums[0];
        dp[1] = max(nums[0], nums[1]);
        for (int i = 2; i < nums.size(); i++) {
            dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);
        }
        return dp[nums.size() - 1];
    }
};

Java代码代码如下:

class Solution {
    public int rob(int[] nums) {
        if (nums == null || nums.length == 0) return 0;
        if (nums.length == 1) return nums[0];

        int[] dp = new int[nums.length];
        dp[0] = nums[0];
        dp[1] = Math.max(dp[0], nums[1]);
        for (int i = 2; i < nums.length; i++) {
            dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]);
        }

        return dp[nums.length - 1];
    }
}
目录
相关文章
SQL 个版本下载地址
备用:   SQL Server 2016简体中文企业版 文件名:cn_sql_server_2016_enterprise_x64_dvd_8699450.iso 64位下载地址:ed2k://|file|cn_sql_server_2016_enterprise_x64_dvd_8699450.
2545 0
|
4月前
|
机器学习/深度学习 自然语言处理 PyTorch
【笔记】激活函数SiLU和Swish
激活函数 SiLU 和 Swish 都是 深度学习 中用于神经网络中的非线性激活函数,旨在增强模型的表达能力和训练性能。实际上,SiLU(Sigmoid Linear Unit)和 Swish 本质上是同一个激活函数的两种不同名称。
317 0
|
4月前
|
负载均衡 监控 测试技术
【干货满满】高性能API调用方案:如何突破频率限制+异步请求优化
在电商 API 开发中,频率限制常成性能瓶颈。本文提出一套高性能方案,结合异步请求、批量处理、智能限流等技术,显著提升调用效率,突破平台限制,实现稳定高效的数据交互。
|
7月前
|
安全 Linux 网络安全
在Linux(CentOS和AWS)上安装更新的git2的方法并配置github-ssh
经过以上这些步骤,你现在就能在GitHub上顺利往返,如同海洋中的航海者自由驰骋。欢迎你加入码农的世界,享受这编程的乐趣吧!
322 10
|
10月前
|
机器学习/深度学习 PyTorch 测试技术
LossVal:一种集成于损失函数的高效数据价值评估方法
LossVal是一种创新的机器学习方法,通过在损失函数中引入实例级权重,直接在训练过程中评估数据点的重要性,避免了传统方法中反复重训练模型的高计算成本。该方法适用于回归和分类任务,利用最优传输距离优化权重,确保模型更多地从高质量数据中学习。实验表明,LossVal在噪声样本检测和高价值数据点移除等任务上表现优异,具有更低的时间复杂度和更稳定的性能。论文及代码已开源,为数据价值评估提供了高效的新途径。
237 13
LossVal:一种集成于损失函数的高效数据价值评估方法
|
10月前
|
存储 自然语言处理 文字识别
开放应用架构,建设全新可精细化运营的百炼
本次分享的主题是开放应用架构,建设全新可精细化运营的百炼。由阿里云智能集团专家团队介绍在过去一年中,百炼在RAG(检索增强生成)技术的应用落地所遇到的挑战及解决方案。
274 11
Threejs创建胶囊体
这篇文章介绍了在Three.js中创建胶囊体(两端为半球形中间为圆柱形的模型)的方法,包括建立几何体、设置材质以及将其添加到场景中的步骤。
156 1
Threejs创建胶囊体
|
网络安全 数据安全/隐私保护
什么是 CSRF 攻击
CSRF(跨站请求伪造)攻击是指攻击者诱导用户点击恶意链接或提交表单,利用用户已登录的身份在目标网站上执行非授权操作,如转账、修改密码等。这种攻击通常通过嵌入恶意代码或链接实现。
|
弹性计算 安全 Python
编程之美:几行代码带你走进雪的世界
冬季来临,用Python的`turtle`库绘制美丽的雪花图案。代码包括设置绘图窗口、定义雪花颜色、绘制雪花的递归函数以及绘制多个随机位置和大小的雪花。运行代码,享受雪花飘落的视觉盛宴。
303 5
|
机器学习/深度学习 并行计算 PyTorch
提高 PyTorch 性能
提高 PyTorch 是一个非常流行的深度学习框架,它支持动态计算图,非常适合快速原型设计和研究。
349 3