打劫房屋I:

题目内容:

假设你是一个专业的窃贼,准备沿着一条街打劫房屋。每个房子都存放着特定金额的钱。你面临的唯一约束条件是:相邻的房子装着相互联系的防盗系统,且 当相邻的两个房子同一天被打劫时,该系统会自动报警。给定一个非负整数列表,表示每个房子中存放的钱, 算一算,如果今晚去打劫,你最多可以得到多少钱 在不触动报警装置的情况下。

样例:

给定 [3, 8, 4], 返回 8.

挑战:

O(n) 时间复杂度 且 O(1) 存储。

算法分析:

前提:对于某一间房子i,如果盗贼要打劫该房子,则房间对序号为i-1的房子(即前一所房子)盗贼不能进行打劫才能保证系统不报警。因此,很容易得出动态规划的表达式:

  ①建立一个数组DP[],DP[i]用来表示盗贼打劫到第i所房子时所能获得的最大金额数;

  ②根据前提的描述,盗贼不打劫当前房子,则DP[i] = DP[i-1];否则DP[i] = DP[i-2] + A[i];

因此DP[i] = max{ DP[i-1], DP[i-2] + A[i]};

代码:

public class Solution {/** @param A: An array of non-negative integers* @return: The maximum amount of money you can rob tonight*//*时间开销为O(n) 空间开销为O(n);public long houseRobber(int[] A) {// write your code hereif(A.length==0){return 0;}long[] DP = new long[A.length+1];DP[1] = A[0];for(int i=1;i<A.length;i++){DP[i+1] = Math.max(DP[i-1]+A[i],DP[i]);}return DP[A.length];}*///空间开销为O(1);public long houseRobber(int[] A) {if(A.length==0){return 0;}if(A.length==1){return A[0];}long DP_i_1 = A[1];long DP_i_2 = A[0];for(int i=2;i<A.length;i++){long temp = DP_i_1;DP_i_1 = Math.max(temp,DP_i_2+A[i]);DP_i_2 = temp;}return DP_i_1;}
}

打劫房屋II:

题目内容:

在上次打劫完一条街道之后,窃贼又发现了一个新的可以打劫的地方,但这次所有的房子围成了一个圈,这就意味着第一间房子和最后一间房子是挨着的。每个房子都存放着特定金额的钱。你面临的唯一约束条件是:相邻的房子装着相互联系的防盗系统,且 当相邻的两个房子同一天被打劫时,该系统会自动报警。给定一个非负整数列表,表示每个房子中存放的钱, 算一算,如果今晚去打劫,你最多可以得到多少钱 在不触动报警装置的情况下。

注意事项:

这题是House Robber的扩展,只不过是由直线变成了圈。

样例:

给出nums = [3,6,4], 返回 6, 你不能打劫34所在的房间,因为它们围成一个圈,是相邻的。

算法分析:

本题在打劫房屋I的基础上增加了一个条件就是第一所房子与最后一所房子也不能兼得,其实本质并没有发生变化。在I中我们的建立的动态规划数组为DP[i]表示盗贼打劫到第i所房子获利的最大值,因此我们同样可以建立两个数组DP_1[] 和 DP_2[] 分别用来记录打劫区间为[1, n-1] 与 [2,n]的获利情况。这是因为第一所房子与最后一所房子不能够相邻,因此将其分为两个区间[1,n-1]与[2,n]后则就将问题化为了直线的打劫问题,也就可以运用I中的方法求解。

代码:

public class Solution {/** @param nums: An array of non-negative integers.* @return: The maximum amount of money you can rob tonight*/public int houseRobber2(int[] nums) {// write your code hereif(nums.length==0||nums.length==2||nums==null){return 0;}if(nums.length==1){return nums[0];}int[] DP_1 = new int[nums.length-1];int[] DP_2 = new int[nums.length-1];//不打劫最后一所房子则从第一所房子开始打劫for(int i=0;i<nums.length-1;i++){if(i==0){DP_1[i] = nums[0];}if(i==1){DP_1[i] = Math.max(nums[1],DP_1[0]);}if(i>1){DP_1[i] = Math.max(DP_1[i-2]+nums[i],DP_1[i-1]);}}//打劫最后一所房子则从第二所房子开始打劫for(int i=1;i<nums.length;i++){if(i==1){DP_2[i-1] = nums[1];}if(i==2){DP_2[i-1] = Math.max(nums[2],DP_2[0]);}if(i>2){DP_2[i-1] = Math.max(DP_2[i-3]+nums[i],DP_2[i-2]);}}return DP_1[nums.length-2]>DP_2[nums.length-2]?DP_1[nums.length-2]:DP_2[nums.length-2];}
}

打劫房屋III:

题目描述:

在上次打劫完一条街道之后和一圈房屋之后,窃贼又发现了一个新的可以打劫的地方,但这次所有的房子组成的区域比较奇怪,聪明的窃贼考察地形之后,发现这次的地形是一颗二叉树。与前两次偷窃相似的是每个房子都存放着特定金额的钱。你面临的唯一约束条件是:相邻的房子装着相互联系的防盗系统,且当相邻的两个房子同一天被打劫时,该系统会自动报警。算一算,如果今晚去打劫,你最多可以得到多少钱,当然在不触动报警装置的情况下。

样例:

  3/ \
2   3\   \ 3   1

窃贼最多能偷窃的金钱数是 3 + 3 + 1 = 7.

    3/ \4   5/ \   \
1   3   1

窃贼最多能偷窃的金钱数是 4 + 5 = 9.

算法分析:

打劫房屋I、II均为对数组的动态规划处理,但本题是要求对二叉树进行一个动态规划处理。对于本题,首先要了解怎样是相邻:有直接连接的节点之间算相邻节点,即父节点与亲子节点;

对于二叉树中的某一个节点i,它也有偷与不偷这两个选项,若偷,则两个子节点不能偷;否则,两个子节点可以偷。与I、II不同的是,I、II中对当前的房屋i,偷与不偷仅需把其中的较大者保留下来进行,因为后续的结果均是建立在前者为最优解的基础上进行的,而且DP[i] = max{DP[i-1],DP[i-2]+A[i]}一定能保证不发生冲突;但是对于二叉树,当前节点i并不能那么方便的找到其子节点的子节点的最优解,因此并不能同I、II那样仅记录最优解。对于二叉树的节点而言,其最容易访问到的就是它的两个子节点。因此,可以建立一个大小为2的一维数组DP,其中DP[0]用来记录偷当前节点所能获利值,DP[1]用来记录不偷当前的值所能获利的值。因为二叉树由根节点开始进行发散,因此可以用后序遍历的方式最终返回一个二维数组。动态规划表达式如下:

  对于某一个节点node,若偷:DP[0] = left[1] + right[1] + node.val; 若不偷:DP[1] = max{left[0],left[1]} + max{right[0],right[1]};

代码:

/*** Definition of TreeNode:* public class TreeNode {*     public int val;*     public TreeNode left, right;*     public TreeNode(int x) { val = x; }* }*/public class Solution {/** @param root: The root of binary tree.* @return: The maximum amount of money you can rob tonight*/public int[] postTrack(TreeNode node){if(node==null){int[] result = new int[]{0,0};return result;}int[] result = new int[2];int[] left = postTrack(node.left);int[] right = postTrack(node.right);//偷当前结点result[0] = left[1] + right[1] + node.val;//不偷当前节点 result[1] = Math.max(left[0],left[1]) + Math.max(right[0],right[1]);return result;}public int houseRobber3(TreeNode root) {// write your code hereint[] result = postTrack(root);return Math.max(result[0],result[1]);}
}

  

  

转载于:https://www.cnblogs.com/Revenent-Blog/p/7569620.html

LintCode刷题——打劫房屋I、II、III相关推荐

  1. 二、lintcode刷题记录--二叉树的路径和

    LintCode刷题记录---二叉树的路径和(效率可能没有那些专业的高,主要是代码结构比较简单) ) 题目地址:http://www.lintcode.com/zh-cn/problem/binary ...

  2. java刷题--518零钱兑换II

    java刷题--518零钱兑换II 题目 代码 结果 题目 代码 class Solution {public int change(int amount, int[] coins) {int[] d ...

  3. LintCode刷题:有效数字

    今天第一次是跟随一个博主学习足迹知道有LintCode 和LeetCode这两个刷题网址,专为学编程的同志练手,我希望我可以每天坚持刷一题!!!! 第一次不知道直接点"帮我挑一题" ...

  4. LintCode刷题——不同的二叉查找树I、II

    不同的二叉查找树I: 题目内容: 给出 n,问由 1...n 为节点组成的不同的二叉查找树有多少种? 样例: 给出n = 3,有5种不同形态的二叉查找树: 1 3 3 2 1\ / / / \ \3 ...

  5. 每日算法刷题Day5-平方矩阵II和III、蛇形矩阵图解

    ⭐每日算法题解系列文章旨在精选重点与易错的算法题,总结常见的算法思路与可能出现的错误,与笔者另一系列文章有所区别,并不是以知识点的形式提升算法能力,而是以实战习题的形式理解算法,使用算法.

  6. LintCode 买卖股票的最佳时机I II III IV

    今天我做了LintCode上的买卖股票系列题目.总共4道题目,主要使用了动态规划的方法,在此写出我的代码和思路以便交流和回顾. 1.假设有一个数组,它的第i个元素是一支给定的股票在第i天的价格.如果你 ...

  7. LintCode刷题(入门篇)

    最近在玩LintCode上面的算法题.下面分享一下部分题目的答案.如果其他同学有更好的答案,可以和我交流讨论,本人菜鸟一个,各位大佬多指点. 同时说一下,这个上面的二叉树 和 链表 我不懂,所以这类题 ...

  8. lintcode刷题 14. 二分查找,迭代和二分法Python实现

    14. 二分查找 描述 给定一个排序的整数数组(升序)和一个要查找的整数target,用O(logn)的时间查找到target第一次出现的下标(从0开始),如果target不存在于数组中,返回-1. ...

  9. leetcode刷题:不同路径II

    分析: 我们用 f(i, j)f(i,j) 来表示从坐标 (0, 0)(0,0) 到坐标 (i, j)(i,j) 的路径总数,u(i, j)u(i,j) 表示坐标 (i, j)(i,j) 是否可行,如 ...

最新文章

  1. 成为年薪50W+的NLP工程师,需要哪些技能?
  2. CSDN网站用户数据库给破了
  3. AD20学习笔记3---PCB封装库的创建方法及现有封装调用
  4. LocalDateTime与LocalDate之间的相互转换
  5. python打log_python根据文件大小打log日志
  6. viewController详解
  7. 分布式系统面试 - 幂等性设计
  8. 内购订单进行二次处理_更学教育:卖家在投诉异常订单的流程是怎么样的?
  9. mysql INSERT INTO table2 (column_name(s)) SELECT column_name(s) FROM table1;
  10. 安防布线的一些常见问题。
  11. 单细胞转录组测序数据的可变剪接(alternative splicing)分析方法总结
  12. Excel多个工作簿合成为一个工作表
  13. cherry pick用法
  14. Unable to start debugging.报错
  15. 粉丝测试题的软件,套路得粉丝的答题类H5推荐
  16. 顺序结构,选择结构和循环结构
  17. diskgeniuslinux版_DiskGenius
  18. php指纹登录原理,指纹识别的工作原理-理论方法-敏捷大拇指-一个敢保留真话的IT精英社区...
  19. 35kV电压补偿型SVG(STATCOM)
  20. 关于MySQL安装失败原因

热门文章

  1. postgresql9.6 的安装
  2. ubuntu下python3及idle3的安装
  3. [河南省ACM省赛-第四届] 表达式求值(nyoj 305)
  4. DevExpress学习03——label控件的背景色问题
  5. vs生成命令和属性的宏
  6. shell 脚本初习
  7. 当才华还配不上野心,就静下来学习
  8. mysql_connect 与 memcache_connect
  9. 《软件设计精要与模式》之Factory Method模式
  10. 我做PM(项目经理)这段时间...