首页 > 其他分享 >力扣第198题 打家劫舍

力扣第198题 打家劫舍

时间:2024-09-02 23:51:36浏览次数:12  
标签:198 抢劫 nums 金额 房子 力扣 房屋 打家劫舍 dp

前言

记录一下刷题历程 力扣第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,2,3],我们也可以选择偷最后一间房子,也可以选择不偷。就这样层层分解下去一直到没有房屋可偷或者只剩下一间房子可以偷,可以看到整个过程是存在递归结构的,并且存在重复的子数组[1,2]
和[1],所以既有递归结构又有可以记忆化的重复子问题这就是一道动态规划问题。根据上面的抉择树我们可以得到两个递推公式1.dp[n]=max{dp[n-1],dp[n-2]+nums[n]} 2.dp[0]=0,dp[1]=nums[0]. 根据这两个递推公式我们编写代码。

代码如下:

class Solution {
public:
    int rob(vector<int>& nums) {
        // 创建一个与 nums 大小相同的 dp 数组,用来存储每个位置的最大抢劫金额
        vector<int> dp(nums.size() + 1, 0);
        
        // 如果 nums 数组不为空,则初始化 dp 数组的第一个有效位置
        if (nums.size() > 0) {
            dp[1] = nums[0]; // dp[1] 代表抢劫第一个房子的最大金额
        }

        // 从第二个房子开始,计算每个房子抢劫的最大金额
        for (int i = 2; i < nums.size() + 1; i++) {
            // dp[i-1] 表示不抢劫当前房子时的最大金额
            // dp[i-2] + nums[i-1] 表示抢劫当前房子时的最大金额(不能抢劫 i-1 房子,所以加上 dp[i-2])
            dp[i] = max(dp[i - 1], dp[i - 2] + nums[i - 1]);
        }

        // 返回抢劫所有房子的最大金额
        return dp[nums.size()];
    }
};

解释注释

1.初始化动态规划数组:

创建一个 dp 数组,长度为 nums.size() + 1,用于存储每个房子被抢劫时的最大金额。初始化为 0。

2.处理边界情况:

如果房子的数量大于 0(即数组 nums 不为空),将第一个房子抢劫的最大金额设为 nums[0],即 dp[1] = nums[0]。

3.动态规划填表:

从第二个房子开始,依次计算每个房子被抢劫的最大金额。
dp[i] 代表抢劫前 i 个房子的最大金额。
对于每个房子 i,你有两个选择:
不抢劫当前房子 i,则最大金额为 dp[i - 1]。
抢劫当前房子 i,则不能抢劫前一个房子 i - 1,最大金额为 dp[i - 2] + nums[i - 1]。
选择其中较大的一个作为 dp[i] 的值。

4.返回结果:

返回 dp[nums.size()],即抢劫所有房子时能获得的最大金额。

标签:198,抢劫,nums,金额,房子,力扣,房屋,打家劫舍,dp
From: https://blog.csdn.net/buaichifanqie/article/details/141832414

相关文章

  • 169.力扣-多数元素
    给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊n/2⌋ 的元素。你可以假设数组是非空的,并且给定的数组总是存在多数元素。示例 1:输入:nums=[3,2,3]输出:3示例 2:输入:nums=[2,2,1,1,1,2,2]输出:2方法一:使用排序......
  • Mysql基础练习题 610.判断三角形 (力扣)
    题目:对每三个线段报告它们是否可以形成一个三角形题目连接:https://leetcode.cn/problems/triangle-judgement/description/建表插入数据:CreatetableIfNotExistsTriangle(xint,yint,zint)TruncatetableTriangleinsertintoTriangle(x,y,z)values('13'......
  • 力扣237题详解:删除链表中的节点的模拟面试问答
    在本篇文章中,我们将详细解读力扣第237题“删除链表中的节点”。通过学习本篇文章,读者将掌握如何在单链表中删除给定的节点,并了解相关的复杂度分析和模拟面试问答。每种方法都将配以详细的解释,以便于理解。问题描述力扣第237题“删除链表中的节点”描述如下:请编写一个函......
  • 力扣230题详解:二叉搜索树中第K小的元素的多种解法与模拟面试问答
    在本篇文章中,我们将详细解读力扣第230题“二叉搜索树中第K小的元素”。通过学习本篇文章,读者将掌握如何在二叉搜索树中高效地查找第K小的元素,并了解相关的复杂度分析和模拟面试问答。每种方法都将配以详细的解释,以便于理解。问题描述力扣第230题“二叉搜索树中第K小的元素......
  • 力扣刷题——3007.价值和小于等于 K 的最大数字
    根据题意,不难想到该题的暴力解法,从数字1开始,逐个累加。每次检查由当前数字num所构成的累加价值是否大于k,假如为真,那么可以输出上一个数字,即num-1classSolution{public:longlongfindMaximumNumber(longlongk,intx){longlongsubSum=0;for(lon......
  • c语言--力扣简单题目(两数之和)两种方法讲解
    题目如下:给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。你可以按任意顺序返回答案。示例1:输入:nums=[2,7,11,15],ta......
  • Mysql基础练习题 596.查询至少有5个学生的所有班级 (力扣)
    596.查询至少有5个学生的所有班级建表插入数据:CreatetableIfNotExistsCourses(studentvarchar(255),classvarchar(255))TruncatetableCoursesinsertintoCourses(student,class)values('A','Math')insertintoCourses(student,class)values(......
  • 【dp力扣】买卖股票的最佳时机III
    目录审题通过动态规划固定套路思考:1、定义状态表示(关键)2、推导状态转移方程(重点)对于buy(可买入股票):回顾状态表示:第一种情况:第二种情况:联立两种情况(取两种情况的最大值):​对于own(持有股票)回顾状态表示:第一种情况:第二种情况:(最终结果)联立两种情况(还是取max):3、初......
  • Mysql基础练习题 595.大的国家 (力扣)
            如果一个国家满足下述两个条件之一,则认为该国是大国:面积至少为300万平方公里(即,3000000km2),或者人口至少为2500万(即25000000)编写解决方案找出大国的国家名称、人口和面积,以任意顺序返回结果表。建表插入数据:CreatetableIfNotExistsWorld......
  • 力扣134.加油站
    classSolution{  //定义一个方法,用于判断是否可以完成环路行驶  publicintcanCompleteCircuit(int[]gas,int[]cost){    //初始化当前累加油量和总油量差值    intcurSum=0;    inttotalSum=0;    //初始化起......