动态规划 | 打家劫舍1、2、3

198. 打家劫舍

在这里插入图片描述
https://leetcode.cn/problems/house-robber/description/

dp[i] 表示 考虑到下标为 i (包括i)的房子,可以偷到的最大金额。

dp[i] 有两个状态,分别是 偷 和 不偷。
偷,则需要考虑前 i-2 天的最大金额 + nums[1]。
不偷,则考虑 i-1 天的最大金额即可。
那么递推公式应为:dp[i] = max(dp[i-2] + nums[i], dp[i-1])

dp[0] = nums[0], dp[1] = max(nums[0], nums[1])

class Solution {
    public int rob(int[] nums) {
        if (nums.length == 1) {
            return nums[0];
        }
        int[] dp = new int[nums.length];
        
        dp[0] = nums[0];
        dp[1] = Math.max(nums[0], nums[1]);
        for (int i = 2; i < nums.length; i++) {
            dp[i] = Math.max(dp[i-2] + nums[i], dp[i-1]);
            // System.out.println(Arrays.toString(dp));
        }
        return dp[nums.length - 1];
    }
}

213. 打家劫舍 II

在这里插入图片描述
房子首尾相连,只有三种情况,
第一,首尾均不偷
第二,考虑偷首,尾不能投
第三,首不能投,考虑偷尾
第二种和第三种情况包含第一种情况。 两种情况其实就是上一题的思路。

class Solution {
    public int rob(int[] nums) {
        if (nums == null || nums.length == 0) return 0;
        if (nums.length == 1) return nums[0];
        // 首尾相连,只需要考虑两种情况:考虑包含首元素和考虑包含尾元素
        int res1 = robHelper(nums, 0, nums.length - 1);
        int res2 = robHelper(nums, 1, nums.length);
        
        return Math.max(res1, res2);
    }

    private int robHelper(int[] nums, int start, int end) {

        if (start == end - 1) return nums[start];

        int[] dp = new int[nums.length];
        dp[start] = nums[start];
        dp[start + 1] = Math.max(nums[start], nums[start + 1]);

        for (int i = start + 2; i < end; i++) {
            dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]);
            // System.out.println(Arrays.toString(dp));
        }
        
        return dp[end - 1];
    }
}

337. 打家劫舍 III

在这里插入图片描述

暴力递归 and 记忆化递归:

每个节点有两种状态,偷和不偷
偷,则不能偷左右子节点
不偷,则可以考虑偷左右子节点,注意是考虑,也有可能不偷。

Map<TreeNode, Integer> map = new HashMap<>();
public int rob2(TreeNode root) {
    // 记忆化递归, 1ms
    if (root == null) return 0;
    if (root.left == null && root.right == null) return root.val;
    if (map.containsKey(root)) return map.get(root);

    // 偷父节点
    int val1 = root.val;
    if (root.left != null) val1 += rob(root.left.left) + rob(root.left.right);
    if (root.right != null) val1 += rob(root.right.left) + rob(root.right.right);

    // 不偷父节点
    int val2 = rob(root.left) + rob(root.right);
    map.put(root, Math.max(val1, val2));
    return Math.max(val1, val2);
}

动态规划:
这道题目算是树形dp的入门题目,因为是在树上进行状态转移,我们在讲解二叉树的时候说过递归三部曲,那么下面我以递归三部曲为框架,其中融合动规五部曲的内容来进行讲解。

  1. 确定递归函数的参数和返回值:

    其实这里的返回数组就是dp数组。

    所以dp数组(dp table)以及下标的含义:下标为0记录不偷该节点所得到的的最大金钱,下标为1记录偷该节点所得到的的最大金钱。所以本题dp数组就是一个长度为2的数组!
    而且,递归的每一层都会保存当前节点的 dp 数组

  2. 确定终止条件
    即,当参数 root 为 null 时,返回[0, 0] 数组

  3. 确定遍历顺序
    一定是后续遍历,因为需要递归返回值,来做下一步计算。
    通过递归左节点,得到左节点偷与不偷的金钱。
    通过递归右节点,得到右节点偷与不偷的金钱。

  4. 确定单层递归的逻辑
    如果是偷当前节点,那么左右孩子就不能偷,val1 = root.val + left[0] + right[0]; (如果对下标含义不理解就再回顾一下dp数组的含义)
    如果不偷当前节点,那么考虑偷左右孩子,即取其中最大的即可 val2 = max(left[0], left[1]) + max(right[0], right[1])
    最后当前节点的状态就是{val2, val1}; 即:{不偷当前节点得到的最大金钱,偷当前节点得到的最大金钱}

  5. 举例推导dp数组

class Solution {

    public int rob(TreeNode root) {
        int[] res = robTree(root);
        return Math.max(res[0], res[1]);
    }

    private int[] robTree(TreeNode root) {
        if (root == null) return new int[]{0, 0};
        // 后续遍历
        int[] left = robTree(root.left);
        int[] right = robTree(root.right);
        
        // 偷当前节点,那么就不能偷左右节点。
        int val1 = root.val + left[0] + right[0];
        // 不偷当前节点,那么就考虑偷左右节点,可偷可不偷,即取较大的情况
        int val2 = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
        return new int[]{val2, val1};
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Google Colab 现已支持直接使用 transformers 库

Google Colab&#xff0c;全称 Colaboratory&#xff0c;是 Google Research 团队开发的一款产品。在 Colab 中&#xff0c;任何人都可以通过浏览器编写和执行任意 Python 代码。它尤其适合机器学习、数据分析和教育目的。从技术上来说&#xff0c;Colab 是一种托管式 Jupyter …

Mysql窗口函数

1 什么是窗口函数 MySQL从8.0开始支持窗口函数&#xff0c;有的也叫分析函数&#xff08;处理相对复杂的报表统计分析场景&#xff09;&#xff0c;这个功能在大多商业数据库和部分开源数据库中早已支持。 窗口函数&#xff1a;窗口、函数&#xff08;应用在窗口内的函数&…

Dockerfile与Docker网络

一、Dockerfile 1、概念&#xff1a; Dockerfile是用来构建docker镜像的文本文件&#xff0c;是由构建镜像所需要的指令和参数构建的脚本。 2、构建步骤&#xff1a; ① 编写Dockerfile文件 ② docker build命令构建镜像 ③ docker run依据镜像运行容器实例 Dockerfile …

深入理解:Class.getResource与ClassLoader.getResource使用区别

深入理解&#xff1a;Class.getResource与ClassLoader.getResource使用区别 一作用&#xff1a;都是使用类的类加载器来读取某个文件&#xff0c;从而获取该文件的URL对象二Class.getResource()方法读取文件&#xff1a;1.若文件路径以“/”开头&#xff0c;则该方法会从classp…

洛谷 P9516 color C++代码

目录 前言 思路点拨 AC代码 结尾 前言 今天我们来做洛谷上的一道题目。 网址&#xff1a;color - 洛谷 题目&#xff1a; 思路点拨 这题就是if-else判断输入的五个数据和不就OK了&#xff1f; 在这里我的估值是183&#xff08;截止2023.12.3&#xff09;&#xff0c;热…

软件工程单选多选补充

2. 4. 5. 6. 7. 8. 9. 10. 12。 13.

Zabbix监控接收SNMPTrap消息与SNMPTT结合

一.SNMP 协议 1.协议介绍 snmp 协议是日常使用的较多的一种协议&#xff0c;绝大多数网络设备/存储等都支持 snmp 协议&#xff0c;通过此协议可以实现设备状态的监控及管理。 2.主要组成 SNMP 协议包括以下三个部分: SNMP Agent&#xff1a;负责处理 snmp 请求&#xff0c…

k8s中批量处理Pod应用的Job和CronJob控制器、处理守护型pod的DaemonSet控制器介绍

目录 一.Job控制器 1.简介 2.Jobs较完整解释 3.示例演示 4.注意&#xff1a;如上例的话&#xff0c;执行“kubectl delete -f myJob.yaml”就可以将job删掉 二.CronJob&#xff08;简写为cj&#xff09; 1.简介 2.CronJob较完整解释 3.案例演示 4.如上例的话&#xf…

应用安全四十三:无密码认证安全

什么是无密码认证&#xff1f; 无密码认证是一种新兴的安全技术和身份认证手段&#xff0c;是用密码以外的东西验证软件用户身份的过程&#xff0c;旨在替代传统的用户账号和密码认证方法&#xff0c;提高账号的安全性和用户体验。无密码技术通过生物识别、多因素认证、基于硬…

长度最小的子数组(Java详解)

目录 题目描述 题解 思路分析 暴力枚举代码 滑动窗口代码 题目描述 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl1, ..., numsr-1, numsr] &#xff0c;并返回其长度。如果不存在符合条…

Prime 1.0

信息收集 存活主机探测 arp-scan -l 或者利用nmap nmap -sT --min-rate 10000 192.168.217.133 -oA ./hosts 可以看到存活主机IP地址为&#xff1a;192.168.217.134 端口探测 nmap -sT -p- 192.168.217.134 -oA ./ports UDP端口探测 详细服务等信息探测 开放端口22&#x…

【Linux】进程控制-进程创建

目录 一、fork()是什么&#xff1f; 二、fork返回值问题 1、fork()的两个返回值是什么&#xff1f; 2、fork()为什么有两个返回值&#xff1f; 3、一个变量为什么会保存两个不同的值&#xff1f; 三、写时拷贝 1、写时拷贝是什么 2、为什么要写时拷贝 3、写时拷贝的示意…

GEE:均值滤波

作者:CSDN @ _养乐多_ 本文将介绍在 Google Earth Engine(GEE)平台上,进行均值滤波操作的代码框架、核心函数和多种卷积核。 并分别以林地区域和农田区域为试验区,以NDVI图像为例。结果如下图所示, 文章目录 一、均值滤波二、完整代码三、代码链接一、均值滤波 均值滤…

Docker常用进本命令【必备基本功】

docker常用命令 1.帮助命令 1.查看当前docker 版本 docker version2.查看docker的详细信息 docker info3.docker的帮助命令 docker --help2.镜像命令 镜像命令说明docker images列出本地主机的镜像docker search 镜像名称从docker HUB上搜索镜像docker pull 镜像名称从…

ScyllaDB 基础入门

简介 ScyllaDB 是一种开源的 NoSQL 数据库&#xff0c;它提供了高性能、低延迟的数据处理能力&#xff0c;同时保持了与 Apache Cassandra 高度的兼容性。ScyllaDB 使用了一种名为 “Seastar” 的高效并行编程框架&#xff0c;并采用了 C 进行开发&#xff0c;因此它能够充分利…

Linux 进程状态

操作系统学科的进程状态 新建态&#xff1a;刚刚创建的进程&#xff0c; 操作系统还未把它加入可执行进程组&#xff0c; 它通常是进程控制块已经创建但还未加载到内存中的新进程。就绪态&#xff1a;进程做好了准备&#xff0c;只要有机会就开始执行。阻塞态&#xff1a;进程在…

【富文本编辑器】原生JS使用WangEditor和vue上传图片前后端demo

【富文本编辑器】原生JS使用WangEditor上传图片前后端demo 第一步 HTML 第二步 初始化WangEditor与图片上传回调函数 第三步 后端返回数据体封装 第四步 后端接口上传图片&#xff0c;并返回图片地址 最近&#xff0c;我遇到了这样一个问题&#xff1a;因为我们的项目是基于…

网络和Linux网络_9(应用层和传输层_笔试选择题)

目录 一. 常见应用协议等等 1. 以下不是合法HTTP请求方法的是( ) 2. 文件传输使用的协议是&#xff08;&#xff09; 3. HTTP1.1的请求方法不包括&#xff1f;() 4. http状态码中&#xff0c;( )表示访问成功&#xff0c;( )表示坏请求&#xff0c;( )表示服务不可用。() …

【力扣206】反转链表

【力扣206】反转链表 一.题目描述 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1 &#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1]示例 2 &#xff1a; 输入&#xff1a;head [1,2] 输出&#x…

物奇平台电容触摸功能调试

是否需要申请加入数字音频系统研究开发交流答疑群(课题组)?可加我微信hezkz17, 本群提供音频技术答疑服务,+群赠送语音信号处理降噪算法,蓝牙耳机音频,DSP音频项目核心开发资料, 物奇平台电容触摸功能调试 1 修改按键驱动宏 2 编译生成wpk 文件,import 导入烧录文件。…
最新文章