代码随想录|198.打家劫舍,213.打家劫舍II, 337.打家劫舍 III

news2024/11/20 18:22:29

198.打家劫舍

思路:

题目要求不偷相邻两家,两种偷法,偷法1是偷前k-1间房子,最后一间不偷;偷法2是偷前k-2间房子和最后一间。

代码实现1

class Solution {
    public int rob(int[] nums) {
      
        //偷法1:偷前k-1间房子,最后一间不偷,偷法2:偷前k-2间房子和最后一间
        //dp[k] 对应子问题 f(k),即偷前 k 间房子的最大金额。
        int[] dp=new int[nums.length+1];
        dp[0]=0;
        dp[1]=nums[0];
        for(int i=2;i<dp.length;i++){
            dp[i]=Math.max(dp[i-1],dp[i-2]+nums[i-1]);

        }
        return dp[nums.length];

    }
}

代码实现2

优化,用一个滚动数组,因为每次比较只会涉及3个值,让这3个值轮回循环就可以了

class Solution {
    public int rob(int[] nums) {
         int pre=0,cur=0,tmp;
        //一直只有这三个(pre,cur,tmp轮换)
        for(int num:nums){
            tmp=cur;
            cur=Math.max(pre+num,cur);
            pre=tmp;
        }
        return cur;

    }
}

213.打家劫舍II

这道题在198基础上增加了"环形",其他地方没变,

k神解法,把环形拆成两个子问题

环状排列 意味着第一个房子和最后一个房子中 只能选择一个偷窃,因此可以把此 环状排列房间 问题约化为两个 单排排列房间 子问题:

1.在不偷窃第一个房子的情况下(即 nums[1:]),最大金额是 p1

2.在不偷窃最后一个房子的情况下(即 nums[:n−1]),最大金额是 p2

综合两种情况要找的是max(p1,p2)。

状态定义:dp[i] 代表前 i个房子在满足条件下的能偷窃到的最高金额。

转移方程:

1.设有n间房子,此时向这些房子后加一间房,此房间价值为num;

2.加一间房子后由于不能抢相邻房子,意味着抢第n+1个房间就不能抢第n间;那么前n+1间房能偷取到的最高金额dp[n+1]一定是一下两种情况下的较大值:

    不抢第n+1个房间,因此等于前n个房子的最高金额,即dp[n+1]=dp[n]

    抢第n+1个房间,此时不能抢第n个房间;因此等于前n-1个房子的最高金额加上当前房间价值,即dp[n+1]=dp[n-1]+num;

初始状态:

  • 前 0 间房子的最大偷窃价值为 000 ,即 dp[0]=0

返回值:
  返回 dp列表最后一个元素值,即所有房间的最大偷窃价值。
简化空间复杂度:
  我们发现 dp[n] 只与 dp[n−1] 和 dp[n−2] 有关系,因此我们可以设两个变量 cur和 pre 交替记录,将空间复杂度降到 O(1) 。

代码实现

class Solution {
    public int rob(int[] nums) {
        //分两种情况:1.不偷窃第一个房子(nums[1:],最大金额是p1);2.不偷窃最后一个房子,偷nums[:,n-1],最大金额是p2
        //综合就是要求max(p1,p2)
        if(nums.length==1){return nums[0];}
        return Math.max(myRob(Arrays.copyOfRange(nums,0,nums.length-1)),
        myRob(Arrays.copyOfRange(nums,1,nums.length)));

    }
    //198.题的思路
    int myRob(int[] nums){
        int pre=0,cur=0,tmp;
        //一直只有这三个(pre,cur,tmp轮换)
        for(int num:nums){
            tmp=cur;
            cur=Math.max(pre+num,cur);
            pre=tmp;
        }
        return cur;

    }
}

 337.打家劫舍 III

思路

动态规划其实就是使用状态转移容器来记录状态的变化,可以使用一个长度为2的数组,记录当前节点偷与不偷所得到的的最大金钱。

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

返回值是数组,参数是节点

2.确定终止条件

在遍历的过程中,如果遇到空节点的话,很明显,无论偷还是不偷都是0,所以就返回

3.确定遍历顺序

首先明确的是使用后序遍历。 因为要通过递归函数的返回值来做下一步计算。

通过递归左节点,得到左节点偷与不偷的金钱。

通过递归右节点,得到右节点偷与不偷的金钱。

4.确定单层递归的逻辑

如果是偷当前节点,那么左右孩子就不能偷,val1 = cur->val + left[0] + right[0]; (如果对下标含义不理解就再回顾一下dp数组的含义

如果不偷当前节点,那么左右孩子就可以偷,至于到底偷不偷一定是选一个最大的,所以:val2 = max(left[0], left[1]) + max(right[0], right[1]);

5.举例推导dp数组

用后序遍历的方式推导

最后头结点就是 取下标0 和 下标1的最大值就是偷得的最大金钱

 3.状态标记递归
    // 执行用时:0 ms , 在所有 Java 提交中击败了 100% 的用户
    // 不偷:Max(左孩子不偷,左孩子偷) + Max(又孩子不偷,右孩子偷)
    // root[0] = Math.max(rob(root.left)[0], rob(root.left)[1]) +
    // Math.max(rob(root.right)[0], rob(root.right)[1])
    // 偷:左孩子不偷+ 右孩子不偷 + 当前节点偷
    // root[1] = rob(root.left)[0] + rob(root.right)[0] + root.val;

代码实现 

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int rob(TreeNode root) {
        //广度优先搜索
        int[] res=dfs(root);
        return Math.max(res[0],res[1]);


    }

    int[] dfs(TreeNode root){
        int[] res=new int[2];//res[0]:偷当前节点,res[1]不偷当前节点
        //终止条件
        if(root==null){return res ;}
        //遍历节点顺序
        int[] left= dfs(root.left);//遍历左节点,存储左节点偷,不偷的情况
        int[] right=dfs(root.right);
        /**
        res[0]=root.val+left[0]+right[0];
        res[1]=Math.max(left[0],left[1])+Math.max(right[0],right[1]);
         */
        //不偷当前节点,左右孩子不偷
        res[1]=root.val+left[0]+right[0];
        //偷当前节点,考虑偷左还是
        res[0]=Math.max(left[0],left[1])+Math.max(right[0],right[1]);

        
        return res;


    }
}

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

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

相关文章

ts工具类

这里有具体的使用示例&#xff1a; 15 种TypeScript最常用的实用程序类型&#xff0c;赶快收藏起来吧&#xff01; - 知乎我们在使用 TypeScript 的过程中&#xff0c;我们是面向类型编程的&#xff0c;为了满足不同的工作场景&#xff0c;我们需要对已知类型进行改造。 为了…

Ubuntu下Nginx配置ModSecurity详细思路及过程

下面是一个简介&#xff1a; Ubuntu是一个linux操作系统&#xff0c;Nginx是一个web服务器软件&#xff0c;ModSecurity是一款开源的web应用防火墙&#xff08;江湖人称“WAF”&#xff09;。 如果上面的概念没有一定的了解&#xff0c;下面的内容其实也能看。就是不好操作。…

(典题)线段计数 CF690 div3 F

Problem - F - Codeforces 题意&#xff1a; 思路&#xff1a; 这题没什么性质可言&#xff0c;可以说就是纯纯的套路题 既然存在一条线段和其他所有线段相交&#xff0c;不知道是哪条线段&#xff0c;考虑枚举这条线段&#xff0c;然后计数没有交点的线段个数&#xff0c;取…

输电线路故障诊断(Python代码,逻辑回归、决策树、随机森林、XGBoost和支持向量机五种不同方法诊断)

效果视频&#xff1a;输电线路故障诊断&#xff08;Python代码&#xff0c;逻辑回归、决策树、随机森林、XGBoost和支持向量机五种不同方法诊断&#xff09;_哔哩哔哩_bilibili 1.数据 仿真平台 仿真模型分别获取单相接地故障、两相接地故障、两相间短路故障、三相接地故障、…

通过多个url下载合并zip包

在网上随便找两个网络URL入参 {"fileUrls": ["url1","url2","url3""zipName":"xxxx" }Overridepublic void getUrlsToZip(UrlDownLoadFileParam urlDownLoadFileParam,HttpServletResponse response ) throws Ex…

排序算法-归并排序

属性 归并排序&#xff08;MERGE-SORT&#xff09;是建立在归并操作上的一种有效的排序算法,该算法是采用分治法&#xff08;Divide and Conquer&#xff09;的一个非常典型的应用。将已有序的子序列合并&#xff0c;得到完全有序的序列&#xff1b;即先使每个子序列有序&#…

k8s集群中部署服务之部署描述文件准备

微服务部署描述文件Deploy.yaml 一、各微服务创建部署描述文件 1.1 mall-auth-server --- apiVersion: apps/v1 kind: Deployment metadata:name: mall-auth-servernamespace: sangomalllabels:app: mall-auth-server spec:replicas: 1selector:matchLabels:app: mall-auth-s…

生产消费者模型的介绍以及其的模拟实现

目录 生产者消费者模型的概念 生产者消费者模型的特点 基于阻塞队列BlockingQueue的生产者消费者模型 对基于阻塞队列BlockingQueue的生产者消费者模型的模拟实现 ConProd.c文件的整体代码 BlockQueue.h文件的整体代码 对【基于阻塞队列BlockingQueue的生产者消费者模型…

css 清除浮动方案

清除浮动的三种方案 1. 第一种方案&#xff08;overflow: hidden&#xff09;2. 第二种方案&#xff08;clear&#xff1a;both&#xff09;3. 第三种方案&#xff08;为元素&#xff09; 1. 第一种方案&#xff08;overflow: hidden&#xff09; <style>.container {bac…

以AI对抗AI,大模型安全的“进化论”

点击关注 文丨刘雨琦&#xff0c;编&#xff5c;王一粟 “互联网时代&#xff0c;我们是更危险&#xff0c;还是更安全&#xff1f;” 2016年&#xff0c;互联网正值高速发展之际&#xff0c;电梯广告经常出现这几个大字&#xff0c;两行标语&#xff0c;从病毒木马到网络诈骗…

焕发生机|嵌入式存储eMMC原理解析

1.EMMC背景回顾 EMMC存储的发展历史可以追溯到1997年&#xff0c;当时该技术是为了解决移动设备中存储器的问题而提出的。当时移动设备的存储器主要是NOR flash&#xff0c;这种存储器虽然读写速度快&#xff0c;但是造价高、容量小&#xff0c;不适合大规模应用。而EMMC的出现…

JWT安全及案例实战

文章目录 JWT 安全1. Cookie2. Session3. Token4. JWT4.1 JWT概述4.1.1 JWT头4.1.2 有效载荷4.1.3 签名哈希4.1.4 通信流程 4.2 JWT 漏洞描述4.3 JWT 漏洞原理4.4 JWT 安全防御 5. WebGoat 靶场实验5.1 第四关5.2 第五关5.3 第七关 越权与逻辑漏洞 Web漏洞点只有一个入口&#…

Vue开发小注意点

改bug 更改了配置项啥的&#xff0c;保存刷新发现没变&#xff0c;那就重启项目&#xff01;&#xff01;&#xff01;&#xff01; binding.value 和 e.target.value binding.value Day5 指令的值 e.target.value Day4 表单组件封装 binding.value 和 e.target.valu…

hiredis在vs2010上编译不通过

下载源代码 https://github.com/redis/hiredis 然后单独创建pro文件&#xff0c;将相应的.c和.h文件加进去。 然后使用vs2010&#xff08;带有qt插件&#xff09;打开.pro文件&#xff0c;编译报错 上面的为C99语法&#xff0c;而vs2010不支持。只能选择 https://github.com/…

API原理概念篇(六)玩转正则表达式等常用API

一 玩转正则表达式等常用API ① 正则 1、openresty存在两套正则表达式规范1) lua自身独有的正则规范 备注&#xff1a;大约有5%&#xff5e;15%性能损耗损耗原因&#xff1a;表达式compile成pattern,并不会被缓存,每次都会被重新compile编译2) nginx的符合POSIX规范的PCR…

[Hadoop] start-dfs.sh ssh报错

Permission denied (publickey 决解方案 相关命令 cd ~/.sshssh-keygen -t rsa -p""cat id_rsa.pub >> authorized_keyschmod 0600 authorized_keys 相关链接Hadoop: start-dfs.sh permission denied - Stack Overflow Java HotSpot(TM) Server VM warning…

分享!JetBrains IDE中的GitLab支持

GitLab是流行的基于git的软件开发和部署平台之一&#xff0c;虽然很长一段时间以来&#xff0c;所有基本git操作都已经可以通过GitLab实现&#xff0c;但GitLab集成仍是JetBrains社区的一大最热门请求。为此&#xff0c;JetBrains团队今年与GitLab联手提供了这种类型的集成。 …

【问题记录】解决Git上传文件到GitHub时收到 “GH001: Large files detected” 错误信息!

环境 Windows 11 家庭中文版git version 2.41.0.windows.1GitHub 问题情况 在命令行中使用git上传pdf文件到GitHub服务器时&#xff0c;提示了如下警告信息&#xff1a; 原因是 GitHub 有一个文件大小限制&#xff0c;通常为 100 MB。 如果尝试上传大于此限制的文件&#xff0c…

EMANE中olsrd的调试

1 调试目的 本着学习的态度&#xff0c;对emane tutorial中的示例程序进行重现&#xff0c;以加深对EMANE的理解和掌握。在示例程序0(见https://github.com/adjacentlink/emane-tutorial/wiki/Demonstration-0)中介绍了使用olsrlinkview.py脚本来通过可视化界面观察olsr节点的链…

Marin说PCB之封装设计系列---(01)--非金属化孔的设计总结

提到封装设计小编我刚刚开始学习的时候也是一头雾水&#xff0c;在网上各种找视频学习怎么建封装。在这里小编我也推荐一波凡亿PCB商城上是有封装课程的&#xff0c;我当时就是买的凡亿的封装设计课程自己跟着老师学习的&#xff0c;效果还是挺好的。小编我免费给他们做一波推广…