LeetCode刷题---打家劫舍问题

news2024/12/23 18:35:37

顾得泉:个人主页

个人专栏:《Linux操作系统》  《C/C++》  《LeedCode刷题》

键盘敲烂,年薪百万!


一、打家劫舍

题目链接:打家劫舍

题目描述

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

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

示例 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

解法

1.状态表示:

       对于简单的线性dp,我们可以用「经验+题目要求」来定义状态表示:

            i.以某个位置为结尾,巴拉巴拉;

            ii.以某个位置为起点,巴拉巴拉。

       这里我们选择比较常用的方式,以某个位置为结尾,结合题目要求,定义一个状态表示:

            dp[i]表示:选择到i位置时,此时的最高金额。

       但是我们这个题在1位置的时候,会面临「选择」或者「不选择」两种抉择,所依赖的状态需要细分:

       f[i]表示:选择到i位置时,nums[i]必选,此时的最高金额;

       g[i]表示:选择到i位置时,nums[i]不选,此时的最高金额。

2.状态转移方程:

       因为状态表示定义了两个,因此我们的状态转移方程也要分析两个:

对于f[i]:

       如果nums[i]必选,那么我们仅需知道[i - 1]位置在不选的情况下的最高金额,然后加上nums[i]即可,因此f[i] = g[i - 1]+ nums[i]

对于g[i]:

       如果nums[j]不选,那么[i - 1]位置上选或者不选都可以。因此,我们需要知道[i- 1]位宣上选或者不选两种情况下的最长时长,因此 g[i] = max (f[i - 1],g[i- 1])

3.初始化:

       这道题的初始化比较简单,因此无需加辅助节点,仅需初始化 f[0] = nums[0],g[0] = 0即可

4.填表顺序:

       根据「状态转移方程」得「从左往右,两个表一起填」

5.返回值

       根据「状态表示」,应该返回max(f[n - 1],g[n - 1])

代码实现

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

二、打家劫舍Ⅱ

题目链接:打家劫舍 II

题目描述

       你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。

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

示例 1:

输入:nums = [2,3,2]
输出:3
解释:你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2), 因为他们是相邻的。

示例 2:

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

示例 3:

输入:nums = [1,2,3]
输出:3

提示:

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

解法

       这一个问题是「打家劫舍」问题的变形。

       上一个问题是一个「单排」的模式,这一个问题是一个「环形」的模式,也就是首尾是相连的。但是我们可以将「环形」问题转化为「两个单排」问题:

       a.偷第一个房屋时的最大金额×,此时不能偷最后一个房子,因此就是偷[0,n - 2]区间的房子;

       b.不偷第一个房屋时的最大金额y,此时可以偷最后一个房子,因此就是偷[1,n - 1]区间的房子;

       两种情况下的「最大值」,就是最终的结果

       因此,问题就转化成求「两次单排结果的最大值」

代码实现

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

三、删除并获得点数

题目链接:删除并获得点数

题目描述

       给你一个整数数组 nums ,你可以对它进行一些操作。

       每次操作中,选择任意一个 nums[i] ,删除它并获得 nums[i] 的点数。之后,你必须删除 所有 等于 nums[i] - 1 和 nums[i] + 1 的元素。

       开始你拥有 0 个点数。返回你能通过这些操作获得的最大点数。

示例 1:

输入:nums = [3,4,2]
输出:6
解释:
删除 4 获得 4 个点数,因此 3 也被删除。
之后,删除 2 获得 2 个点数。总共获得 6 个点数。

示例 2:

输入:nums = [2,2,3,3,3,4]
输出:9
解释:
删除 3 获得 3 个点数,接着要删除两个 2 和 4 。
之后,再次删除 3 获得 3 个点数,再次删除 3 获得 3 个点数。
总共获得 9 个点数。

提示:

  • 1 <= nums.length <= 2 * 104
  • 1 <= nums[i] <= 104

解法

       其实这道题依旧是「打家劫舍」问题的变型。我们注意到题目描述,选择×数字的时候,×-1与x+1是不能被选择的。像不像「打家劫舍」问题中,选择i位置的金额之后,就不能选择i - 1位置以及i+1位置的金额呢~

       因此,我们可以创建一个大小为10001(根据题目的数据范围)的hash 数组,将nums 数组中每一个元素×,累加到,hash 数组下标为x的位置处,然后在hash数组上来一次「打家劫舍」即可

代码实现

class Solution {
public:
    int deleteAndEarn(vector<int>& nums) 
    {
        const int n = 10001;
        int arr[n] = {0};
        for(auto x : nums) arr[x] += x;

        vector<int> f(n);
        auto g = f;

        for(int i = 1; i < n; i++)
        {
            f[i] = g[i-1] + arr[i];
            g[i] = max(f[i-1], g[i-1]);
        }
        return max(f[n-1], g[n-1]);
    }
};

结语:今日的刷题分享到这里就结束了,希望本篇文章的分享会对大家的学习带来些许帮助,如果大家有什么问题,欢迎大家在评论区留言~~~ 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1273937.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Git——使用Git进行程序开发

主要介绍个人开发提交记录的主要流程&#xff0c;包括以下内容&#xff1a; 索引- 提交的暂存区。查看工作的状态和内部变更。如何读取用于描述变更的已扩展统一diff格式。支持查询和交互的提交&#xff0c;修改提交。创建、显示和选择&#xff08;切换&#xff09;分支。切换…

FIORI /N/UI2/FLP 始终在IE浏览器中打开 无法在缺省浏览器中打开

在使用/N/UI2/FLP 打开fiori 启动面板的时候&#xff0c;总是会在IE浏览器中打开&#xff0c;无法在缺省浏览器打开 并且URL中包含myssocntl 无法正常打开 启动面板 这种情况可以取消激活ICF节点/sap/public/myssocntl

(项目已开源)社区求助 哪位大佬能不能帮我 将box1 audio 和 box2 slider滑块 和 box3 歌词滚动区域 进行联动

(项目已开源)社区求助 哪位大佬能不能帮我 将box1 audio 和 box2 slider滑块 和 box3 歌词滚动区域 进行联动 链接&#xff1a;https://pan.baidu.com/s/16lpEW6L5jrHfhsG7EXocLw?pwdkryy 提取码&#xff1a;kryy <!--社区求助 哪位大佬能不能帮我 将box1 audio 和 box2 s…

拒绝烂尾,Arm二期持续更新中,Arm二期Roadmap

感谢大家的支持&#xff0c;感谢大家一直以来的鼓励。更感谢大家的包容。近期又更新了很多课程&#xff0c;这次都是总线和协议相关的&#xff0c;适合软件同学基础扫盲。 硬件的同学请自行考虑&#xff0c;相信你们研究的比我这深。同时呢也在规划一些直播讨论交流课&#xff…

文章解读与仿真程序复现思路——电力系统自动化EI\CSCD\北大核心《基于分布鲁棒优化的广义共享储能容量配置方法》

这个标题涉及到储能系统的容量配置方法&#xff0c;具体而言&#xff0c;是一种基于分布鲁棒优化的广义共享储能容量配置方法。让我们逐步解读&#xff1a; 基于分布鲁棒优化&#xff1a; 这表明该方法采用了一种优化技术&#xff0c;即分布鲁棒优化。分布鲁棒优化通常是指在考…

Git常用命令#merge分支合并

要查看所有分支&#xff0c;包括本地和远程仓库的分支&#xff0c;可以使用以下命令&#xff1a; 1.查看分支 1.1 查看本地分支 git branch这个命令会列出本地所有的分支&#xff0c;当前所在的分支会有 * 标记。 1.2 查看远程分支 git branch -r这个命令会列出远程仓库的分…

2023_Spark_实验二十三:Kafka的安装与基本操作

Kafka的安装与基本操作 一、前提工作 二、Kafka安装 三、Kafka基本操作 一、前提工作 必须安装了zookeeper 单机可参考&#xff1a;zookeeper单机安装与配置 集群可参考&#xff1a;zookeeper的集群安装 二、Kafka安装 上传kafka_2.11-2.4.1.tgz到/tools目录下 解压安装到…

vue使用el-select el-option失效 不显示名称 还是显示原数据

<el-form-item label"生效标记" prop"enableSign" label-width"17rem"><el-select v-model"dialog.elForm.enableSign" placeholder"请选择内容"><el-option v-for"item in enableSignList":key&q…

SpringBoot+Redis获取电脑信息

获取电脑信息 测试 System.getProperties(); System: 是Java中的一个内置类&#xff0c;用于提供与系统相关的功能和信息。这个类中包含了一些静态方法和常量&#xff0c;可以让您方便地访问和操作系统级别的资源。 getProperties(): 是一个静态方法&#xff0c;它返回一个表示…

Linux:理解文件重定向

文章目录 文件内核对象fd的分配问题重定向的现象dup2 重定向的使用标准输出和标准错误 前面对于文件有了基本的认知&#xff0c;那么基于前面的认知&#xff0c;本篇总结的是文件重定向的含义极其本质 文件内核对象 首先理解一下file内核对象是什么&#xff0c;回顾一下下面这…

菜鸟学习日记(Python)——基本数据类型

Python 中的变量不需要声明。每个变量在使用前都必须赋值&#xff0c;变量赋值以后该变量才会被创建。 在 Python 中&#xff0c;变量就是变量&#xff0c;它没有类型&#xff0c;我们所说的"类型"是变量所指的内存中对象的类型。 等号&#xff08;&#xff09;用来…

Netty Review - 探索Channel和Pipeline的内部机制

文章目录 概念Channel Pipeline实现原理分析详解 Inbound事件和Outbound事件演示Code 概念 Netty中的Channel和Pipeline是其核心概念&#xff0c;它们在构建高性能网络应用程序时起着重要作用。 Channel&#xff1a; 在Netty中&#xff0c;Channel表示一个开放的连接&#xff…

【VScode】超详细图片讲解下载安装、环境配置、编译执行、调试

这里是目录 VScode是什么&#xff1f;VScode的下载和安装环境介绍安装中文插件 配置VScodeC/C开发环境下载和配置MinGW-w64 编译器套件下载&#xff1a;配置&#xff1a; 安装C/C插件在VScode上编写代码设置C/C编译选项创建执行任务编译执行如果想写其他代码在同一个文件夹在不…

【双向链表的实现】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 1. 双向链表的结构 2. 双向链表的实现 2.1 头文件 ——双向链表的创建及功能函数的定义 2.2 源文件 ——双向链表的功能函数的实现 2.3 源文件 ——双向链表功能的…

SS6811H38V/1.6A 两通道 H 桥驱动芯片

SS6811H 为舞台灯光和其它电机一体化应用 提供一种双通道集成电机驱动方案。SS6811H 有 两路 H 桥驱动&#xff0c;每个 H 桥可提供最大输出电流 1.6A (在 24V 和 Ta 25C 适当散热条件下)&#xff0c;可驱 动两个刷式直流电机&#xff0c;或者一个双极步进电机&#xff0c;或 …

ssm+java车辆售后维护系统 springboot汽车保养养护管理系统+jsp

以前汽车维修人员只是在汽车运输行业中从事后勤保障工作,随着我国经济的发展,汽车维修行业已经从原来的从属部门发展成了如今的功能齐备的独立企业。这种结构的转变,给私营汽修企业和个体汽修企业的发展带来了契机,私营企业和个体维修企业的加入也带动了整个汽修行业的整体水平…

[c++]—string类___深度学习string标准库成员函数与非成员函数

要相信别人能做出来自己一定可以做出来&#xff0c;只不过是时间没到而已 目录 &#x1f6a9;string类对象capacity操作 &#x1f4bb;reserve()保留 &#x1f4bb;resize() &#x1f6a9;string类对象元素访问操作 &#x1f4bb;operator[]和at() &#x1f4bb;operator…

Kubernetes 安全最佳实践:保护您的秘密

Kubernetes 是一个可用于微服务的开源容器编排平台。当我们想要部署容器化应用程序、自动化管理和扩展应用程序时&#xff0c;Kubernetes 非常有用。 在容器中运行单个微服务而不是在同一虚拟机中运行多个进程几乎总是更安全。每当我们在 Kubernetes 中启动任何 pod 时&#x…

「黄钊的AI日报·第二季」早鸟票,最后48小时~

每天5条AI内容点&#xff1a;不是新闻汇总&#xff0c;而是站在11年AI产品经理的视角&#xff0c;将原AI信息中的干货认知&#xff0c;提炼成我自己的文字、展示“what I see”。 做社群“AI产品经理大本营”6年以来&#xff0c;我都是在非常用心的输出AI干货&#xff1b;这份“…

vue3随机生成8位字母+数字

// 随机生成8位字母数字 export const autoPassword: any () > {// console.log("自动生成");//可获取的字符串const chars ABCDEFGHIJKLMNOPQRSTUVWSYZabcdefghijklmnopqrstuvwsyz0123456789;const list [];//通过随机获取八个字符串的索引下标for (let i 0;…