输入:一个数组nums,每一个元素nums[i]表示第i个房间的价值。
输出:一个抢劫犯能抢到又不会被警察发现的最大价值。
规则:如果抢劫犯抢了相邻房间,那么报警装置就会触发,警察会得到通知。
分析:我可以从第0个房间开始,可能抢,也可能不抢,一直到最后一个房间,得到的价值取最大值就是结果。用回溯法吧。

public class HouseRobber198 {private int[] nums;private int max = 0;public int rob(int[] nums) {this.nums = nums;max = 0;rob(0,0,true);return max;}private void rob(int idx,int value,boolean robable){if(idx==nums.length){max = Math.max(max,value);}else{//System.out.println(idx+" "+robbed+" "+value);int idx2 = robable?1:0;if(robable){rob(idx+1,value+nums[idx],false);}rob(idx+1,value,true);}}
}

分析2:这样写完,画决策分析树,或者打印idx,robbed,value,就会发现有些是重复的。2 false 重复了两次。因为要计算的是最大价值,所以只需要保留一个最大值。所以我们可以使用缓存减少计算量。

0 false 0
1 true 1
2 false 1
3 true 4
3 false 1
1 false 0
2 true 2
3 false 2
2 false 0
3 true 3
3 false 0
 private int[] nums;private int max = 0;private int[][] memo;public int rob(int[] nums) {this.nums = nums;max = 0;memo = new int[nums.length][2];rob(0,0,true);return max;}private void rob(int idx,int value,boolean robable){if(idx==nums.length){max = Math.max(max,value);}else{//System.out.println(idx+" "+robbed+" "+value);int idx2 = robable?1:0;if(value<memo[idx][idx2]){return;}memo[idx][idx2]=value;if(robable){rob(idx+1,value+nums[idx],false);}rob(idx+1,value,true);}}

分析3:把以上代码改为迭代版本。把变量名memo改为dp。

public int rob(int[] nums) {if(nums==null || nums.length==0) return 0;int n = nums.length;int[][] dp = new int[n][2];dp[0][0] = 0;dp[0][1] = nums[0];for(int i=1;i<n;i++){dp[i][0] = Math.max(dp[i-1][0],dp[i-1][1]);dp[i][1] = dp[i-1][0]+nums[i];}return Math.max(dp[n-1][0],dp[n-1][1]);}

看着写出来的dp代码我发现可以这样整理自己的逻辑。

给定一个数组nums={1,2,3,1}。
如果只有第0个房间,可能抢也可能不抢。但这基本是废话,不抢显然拿不到价值。
  抢,得1,
  不抢得0。
  取最大值,得到的价值是1。
如果只有第0个和第1个 房间。对于房间1可能抢,也可能不抢。
  如果抢第1个房间,那得到的价值是2,因为第0个房间不抢的价值是0。
  如果不抢第1个房间,那得到的价值是1,因为第0个房间抢,得1,不抢得0,取最大值。Max(抢第1个房间,不抢第1个房间)=2。

如果只有第0个、第1个 ,第2个房间。对于房间2可能抢,也可能不抢。
  如果不抢第2个房间,那最后拿到的价值就是Max(抢第1个房间,不抢第1个房间)=2。
  如果抢第2个房间,那最后拿到的价值就是不抢第1个房间的价值+nums[2]=1+3=4。
  那最大的答案是Max(不抢第2个房间,抢第2个房间)=4。
分析到这里我们知道在新增一个房间的时候与上一个房间的抢和不抢获得的价值有关系。最后答案是在当前房间号抢和不抢状态取最大值。这样基本上dp方程就出来了。

我们用dp[i]记录第i个房间的状态,dp[i][0]表示第i个房间不抢的价值,dp[i][1]代表第i个房间抢后的价值。
dp[i][0]=max(dp[i-1][0],dp[i-1][1])
dp[i][1]=dp[i-1][0]+nums[i]

嗯,这就是我的思考方式,是从回溯算法开始,不断优化,最后整理到dp,然后总结出dp应该这样思考。当然还缺少一步是内存优化。只与上一步的状态有关系,可以用变量表示,而无需数组。

 public int robV4(int[] nums) {if(nums==null || nums.length==0) return 0;int n = nums.length;int v0 = 0 ,v1=nums[0];for(int i=1;i<n;i++){int tmp0 = Math.max(v0,v1);int tmp1 = v0+nums[i];v0=tmp0;v1=tmp1;}return Math.max(v0,v1);}

213 House Robber II

class Solution {public int rob(int[] nums) {if(nums==null || nums.length==0) return 0;if(nums.length==1) return nums[0];return Math.max(rob(nums,0,nums.length-2),rob(nums,1,nums.length-1));}public int rob(int[] nums,int start,int end) {int n = nums.length;int[][] dp = new int[2][n];dp[0][start] = nums[start];dp[1][start] = 0;for(int i=start+1;i<=end;i++){dp[0][i] = dp[1][i-1] + nums[i];dp[1][i] = Math.max(dp[0][i-1],dp[1][i-1]);}return Math.max(dp[0][end],dp[1][end]);}
}

[dp]leetcode 198. House Robber相关推荐

  1. LeetCode 198 House Robber Python

    题意:一组直线排列的房屋,一个小偷要进屋偷钱,如果小偷偷了相邻两座房屋就会触发报警系统,问在不触发报警系统的前提下小偷最多可以偷到多少钱. 难度:esay 思路:这是一道标准的动态规划问题,创建一个l ...

  2. LeetCode 198 House Robber(强盗盗窃最大值)(动态规划)(*)

    翻译 你是一个专业强盗,并计划沿街去盗窃每一个住户.每个房子都有一定量的现金,阻止你盗窃的唯一阻碍是相邻的两个房子之间有安全系统.一旦这两个房子同时被盗窃,系统就会自动联系警察.给定一系列非负整数代表 ...

  3. leetcode 337. House Robber III | 337. 打家劫舍 III(树形dp;什么情况下dp需要强制包含当前元素?)

    题目 https://leetcode.com/problems/house-robber-iii/ 思考:什么情况下 dp 需要强制包含当前元素? dp 过程中,需要包含当前元素 的例子: leet ...

  4. LeetCode 198, 213 House Robber

    198 House Robber DP 0~n-1     ans=dp[n-1] dp[i] = max(dp[i-2]+nums[i], dp[i-1])  i>=2 如果要输出偷了那些房子 ...

  5. 动态规划——打家劫舍(Leetcode 198)

    题目选自Leetcode 198 打家劫舍 动态规划解法: 详解过程 如果你对动态规划还不够了解,不着急,咱慢慢来~~ 解题代码: class Solution { public:int rob(ve ...

  6. leetcode 198打家劫舍

    leetcode 198打家劫舍 题目链接:打家劫舍 题目描述:你是一个专业的小偷,计划偷窃沿街的房屋.每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间 ...

  7. leetcode 213. House Robber II | 213. 打家劫舍 II(Java)

    题目 https://leetcode.com/problems/house-robber-ii/ 题解 这道题是「198. 打家劫舍」的进阶,和第 198 题的不同之处是,这道题中的房屋是首尾相连的 ...

  8. leetcode python3 简单题198. House Robber

    1.编辑器 我使用的是win10+vscode+leetcode+python3 环境配置参见我的博客: 链接 2.第一百九十八题 (1)题目 英文: You are a professional r ...

  9. LeetCode 198. 打家劫舍(DP)

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

最新文章

  1. JavaScript数组随机排序
  2. java函数实现进制转换与java实现八进制到十进制的转换(百练OJ:2735:八进制到十进制)
  3. tictoc正方形网络模型_反卷积:可视化并理解卷积网络
  4. 前端常见的安全性问题有哪些?
  5. Linux笔记-bash中字符串拆分并且存到数组中
  6. Flask-SQLAlchemy 对数据库的增查改删
  7. win10系统更新在哪_五步教你win10永久关闭系统自动更新
  8. azure云数据库_Azure中的新弹性数据库
  9. 密集人体姿态估计:2D图像帧可实时生成UV贴图(附论文)
  10. mysql管理密码修改及管理权限设定(zz)
  11. Python基础-计算时间差,时间和,精确到秒,微秒,毫秒
  12. win10鼎信诺为什么安装不了_两个方法教你彻底解决win10系统更新补丁安装失败的问题-系统操作与应用 -亦是美网络...
  13. 【代码笔记】Web--使用Chrome来查看网页源代码
  14. 20脚的RSIC-V MCU,竟然可以基于FOC开发PMSM电机
  15. Excel 2016: 录制宏入门
  16. 数字麦克风PDM信号采集与STM32 I2S接口应用(三)
  17. java日期计算天数_用Java计算两个日期之间的天数
  18. Android手机适配,手机尺寸、px、dpi、dp、sp详解
  19. 哈夫曼树【北邮机试】
  20. html5 sandbox,”基情“无限的IE10和HTML5

热门文章

  1. java基础——equals及==的区别
  2. cdoj 1246 每周一题 拆拆拆~ 分解质因数
  3. GridView控件RowDataBound事件中获取列字段值的几种途径
  4. 【原】两个时间相加的运算符重载实现
  5. 地图图元的闪烁效果制作
  6. java owl文件_jena解析.owl文件 实现owl文件的解析 - 下载 - 搜珍网
  7. Android 监听网络连接状态,判断网络连接方式,9.0网络连接,获取已连接WiFi名称SSID和MAC
  8. Failed to resolve: android.arch.lifecycle:runtime:1.0.0,Failed to resolve: support-v4
  9. 远程桌面无法连接服务器,启动Terminal Services 服务报1053错误
  10. 简述List、Set、Map类型的集合的各自特点