打家劫舍(House Robber)是LeetCode上比较典型的一个题目,涉及三道题,主要解题思想是动态规划,将三道题依次记录如下:

(一)打家劫舍

题目等级:198、House Robber(Easy)

题目描述:

You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night.

Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.

Example 1:

Input: [1,2,3,1]
Output: 4
Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
Total amount you can rob = 1 + 3 = 4.

Example 2:

Input: [2,7,9,3,1]
Output: 12
Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1).
Total amount you can rob = 2 + 9 + 1 = 12.

  题意:你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。


解题思路:

  本题实际就是典型的动态规划问题,沿街的房屋依次决定每一家偷还是不偷为一个阶段,用dp[i]表示前i家获取的最高金额,第i阶段的决策就是两种:偷、不偷。则不难写出以下状态转移方程:

  dp[i]=max(dp[i-1],dp[i-2]+nums[i])

  从以上的递推公式可以看出,第i个状态只和i-1和i-2两个状态有关,因此,也可以省略掉数组,只维护两个变量即可。

//解法一:动态规划(数组)
class Solution {
public int rob(int[] nums) {
//典型的动态规划问题,dp[i]=max(dp[i-1],dp[i-2]+nums[i])
//每个阶段确定一家偷还是不偷,所以决策就是偷和不偷两种
if(nums==null || nums.length==0)
return 0;
int len=nums.length;
int[] res=new int[len+1];
res[0]=0;
res[1]=nums[0];
for(int i=2;i<=len;i++){
res[i]=Math.max(res[i-1],res[i-2]+nums[i-1]); //状态转移
}
return res[len];
}
} //解法二:动态规划(维护两个变量)
class Solution {
public int rob(int[] nums) {
//dp[i]表示前i家可以得到的最高金额,dp[i]=Max(dp[i-1],dp[i-2]+nums[i])
if(nums==null || nums.length==0)
return 0; int first=0,second=0,res=0;
for(int i=0;i<nums.length;i++){
res=Math.max(first+nums[i],second);
first=second;
second=res;
}
return res;
}
}

(二)打家劫舍 II

题目等级:213、House Robber II(Medium)

题目描述:

You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed. All houses at this place are arranged in a circle. That means the first house is the neighbor of the last one. Meanwhile, adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night.

Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.

Example 1:

Input: [2,3,2]
Output: 3
Explanation: You cannot rob house 1 (money = 2) and then rob house 3 (money = 2),
because they are adjacent houses.

Example 2:

Input: [1,2,3,1]
Output: 4
Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
Total amount you can rob = 1 + 3 = 4.

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


解题思路:

  本题和上题基本类似,区别在于:所有的房子围成一个圈,意味着首尾两家也属于相邻。

  基本思路当然还是动态规划,可以划分成两种情况来做,以第一家是否被偷为依据分成两个动态规划问题,如果第一家偷,那么从第一家到第n-1家求最大值(因为意味着最后一家一定不能偷);如果第一家不偷,那么从第2家到第n家求最大值。最后再比较两种情况的最大值即可。

class Solution {
public int rob(int[] nums) {
/*
思路:由于首尾也属于相邻,因此需要分别判断,以第一家是否打劫分成两个问题
第一家抢:最后一家一定不能抢,从第0个到len-2做动态规划
第一家不抢:从1到len-1做动态规划
然后比较找出最大值
*/
if(nums==null || nums.length==0)
return 0;
int len=nums.length;
if(len==1)
return nums[0];
int[] dp1=new int[len];
int[] dp2=new int[len+1];
//第一家抢
dp1[0]=0;
dp1[1]=nums[0];
for(int i=2;i<len;i++)
dp1[i]=Math.max(dp1[i-1],dp1[i-2]+nums[i-1]); //第一家不抢
dp2[0]=0;
dp2[1]=0;
for(int i=2;i<=len;i++)
dp2[i]=Math.max(dp2[i-1],dp2[i-2]+nums[i-1]); return Math.max(dp1[len-1],dp2[len]);
}
}

(三)打家劫舍 III

题目等级:337、House Robber III(Medium)

题目描述:

The thief has found himself a new place for his thievery again. There is only one entrance to this area, called the "root." Besides the root, each house has one and only one parent house. After a tour, the smart thief realized that "all houses in this place forms a binary tree". It will automatically contact the police if two directly-linked houses were broken into on the same night.

Determine the maximum amount of money the thief can rob tonight without alerting the police.

Example 1:

Input: [3,2,3,null,3,null,1]

     3
/ \
2 3
\ \
3 1 Output: 7
Explanation: Maximum amount of money the thief can rob = 3 + 3 + 1 = 7.

Example 2:

Input: [3,4,5,1,3,null,1]

     3
/ \
4 5
/ \ \
1 3 1 Output: 9
Explanation: Maximum amount of money the thief can rob = 4 + 5 = 9.

  题意:在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。 除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警


解题思路:

  和上两题不同的是:本题是二叉树形状,树中直接相连(也就是父子节点)不能同时打劫。

  实际上,有上一题的经验,我们不难找到规律:这里可以按根结点是否打劫分为两种情况,如果根结点被打劫,那么意味着它的子节点都不能打劫,需要直接打劫其孙子辈节点;如果根结点不打劫,那么可以考虑其左右孩子。同时,由于树的特性,左右子树都是子问题,因此实际上就是两种情况分别递归

class Solution {
public int rob(TreeNode root) {
/*
按根偷不偷,分两种情况,分别递归
*/
if(root==null)
return 0;
int res1=0;
//根在结果中
res1+=root.val;
if(root.left!=null)
res1+=(rob(root.left.left)+rob(root.left.right));
if(root.right!=null)
res1+=(rob(root.right.left)+rob(root.right.right)); //根不在结果中
int res2=rob(root.left)+rob(root.right);
return Math.max(res1,res2);
}
}

【LeetCode】打家劫舍系列(I、II、III)的更多相关文章

  1. LeetCode Single Number I / II / III

    [1]LeetCode 136 Single Number 题意:奇数个数,其中除了一个数只出现一次外,其他数都是成对出现,比如1,2,2,3,3...,求出该单个数. 解法:容易想到异或的性质,两个 ...

  2. LeetCode: Combination Sum I && II && III

    Title: https://leetcode.com/problems/combination-sum/ Given a set of candidate numbers (C) and a tar ...

  3. Leetcode 137. Single Number I/II/III

    Given an array of integers, every element appears twice except for one. Find that single one. 本题利用XO ...

  4. 团灭 LeetCode 打家劫舍问题

    有读者私下问我 LeetCode 「打家劫舍」系列问题(英文版叫 House Robber)怎么做,我发现这一系列题目的点赞非常之高,是比较有代表性和技巧性的动态规划题目,今天就来聊聊这道题目. 打家 ...

  5. 【一天一道LeetCode】#260. Single Number III

    一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Given a ...

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

    I 假设有一个数组,它的第i个元素是一支给定的股票在第i天的价格.如果你最多只允许完成一次交易(例如,一次买卖股票),设计一个算法来找出最大利润. II 假设有一个数组,它的第i个元素是一个给定的股票 ...

  7. [array] leetcode - 40. Combination Sum II - Medium

    leetcode - 40. Combination Sum II - Medium descrition Given a collection of candidate numbers (C) an ...

  8. 【一天一道LeetCode】#90. Subsets II

    一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Given a ...

  9. LeetCode 137. Single Number II(只出现一次的数字 II)

    LeetCode 137. Single Number II(只出现一次的数字 II)

  10. LeetCode:路径总和II【113】

    LeetCode:路径总和II[113] 题目描述 给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径. 说明: 叶子节点是指没有子节点的节点. 示例:给定如下二叉树, ...

随机推荐

  1. java 枚举类(简单使用)

    直接上代码 用法一(常量): package com.ou.test; import com.sun.corba.se.impl.util.SUNVMCID; public class Enum { ...

  2. BZOJ 2157: 旅游 (树链剖分+线段树)

    树链剖分后线段树维护区间最大最小值与和. 支持单点修改与区间取反. 直接写个区间取反标记就行了.线段树板题.(200行6000B+ 1A警告) #include <cstdio> #inc ...

  3. k8s权威指南-从xx到oo的实践全接触

    基本概念与术语 集群的2种管理角色:master和node master 集群的控制节点,负责整个集群的管理与控制,运行着关键进程: 1,k8s api server: 提供了HTTP Rest 接口 ...

  4. 微信小程序开发入门教程(一)---hello world

    由于无法备案网站,前期做了个微信小程序(开发版)就搁置了,几乎忘了开发过程.现在重新梳理,做个记录. 一.最基本的小程序前端例子hello 1.下载安装  微信开发者工具  官网: https://d ...

  5. BZOJ 1444: [Jsoi2009]有趣的游戏 AC自动机+概率与期望+矩阵乘法

    这道题还比较友好~首先,构建出来 $AC$ 自动机,那么我们要求的就是从 $0$ 号点走无限次走到一个终止节点的概率. 考虑构建转移矩阵 $M,$ $M_{i,j}$ 表示节点 $i$ 转移到节点 $ ...

  6. 如何查询Office版本号

     造冰箱的大熊猫@cnblogs 2019/1/28 如何查询当前所用Microsoft Office的版本信息? 以Word 2007为例,点击程序左上角的Office图标,在弹出的菜单中选择“Wo ...

  7. 2018 焦作网络赛 G Give Candies ( 欧拉降幂 )

    题目链接 题意 : 给出 N 个糖果.老师按顺序给 1~N 编号的学生分配糖果.每个学生要么不分.要么最少分一个.且由于是按顺序发放.那么对于某个有分到糖果的编号为 i 的学生.则 1~(i-1) 这 ...

  8. 全网最!详!细!tarjan算法讲解。——转载自没有后路的路

    全网最!详!细!tarjan算法讲解.   全网最详细tarjan算法讲解,我不敢说别的.反正其他tarjan算法讲解,我看了半天才看懂.我写的这个,读完一遍,发现原来tarjan这么简单! tarj ...

  9. AtCoder Dwango Programming Contest V E

    题目链接:https://dwacon5th-prelims.contest.atcoder.jp/tasks/dwacon5th_prelims_e 题目描述: 给定一个大小为\(N\)的数组\(A ...

  10. Keras学习笔记二:保存本地模型和调用本地模型

    使用深度学习模型时当然希望可以保存下训练好的模型,需要的时候直接调用,不再重新训练 一.保存模型到本地 以mnist数据集下的AutoEncoder 去噪为例.添加: file_path=" ...