【LeetCode】打家劫舍系列(I、II、III)
打家劫舍(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)的更多相关文章
- LeetCode Single Number I / II / III
[1]LeetCode 136 Single Number 题意:奇数个数,其中除了一个数只出现一次外,其他数都是成对出现,比如1,2,2,3,3...,求出该单个数. 解法:容易想到异或的性质,两个 ...
- LeetCode: Combination Sum I && II && III
Title: https://leetcode.com/problems/combination-sum/ Given a set of candidate numbers (C) and a tar ...
- Leetcode 137. Single Number I/II/III
Given an array of integers, every element appears twice except for one. Find that single one. 本题利用XO ...
- 团灭 LeetCode 打家劫舍问题
有读者私下问我 LeetCode 「打家劫舍」系列问题(英文版叫 House Robber)怎么做,我发现这一系列题目的点赞非常之高,是比较有代表性和技巧性的动态规划题目,今天就来聊聊这道题目. 打家 ...
- 【一天一道LeetCode】#260. Single Number III
一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Given a ...
- 买卖股票的最佳时机I II III IV
I 假设有一个数组,它的第i个元素是一支给定的股票在第i天的价格.如果你最多只允许完成一次交易(例如,一次买卖股票),设计一个算法来找出最大利润. II 假设有一个数组,它的第i个元素是一个给定的股票 ...
- [array] leetcode - 40. Combination Sum II - Medium
leetcode - 40. Combination Sum II - Medium descrition Given a collection of candidate numbers (C) an ...
- 【一天一道LeetCode】#90. Subsets II
一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Given a ...
- LeetCode 137. Single Number II(只出现一次的数字 II)
LeetCode 137. Single Number II(只出现一次的数字 II)
- LeetCode:路径总和II【113】
LeetCode:路径总和II[113] 题目描述 给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径. 说明: 叶子节点是指没有子节点的节点. 示例:给定如下二叉树, ...
随机推荐
- 关于C# Dockpanel的一些入门的基本操作
关于C# Dockpanel的一些入门的基本操作 原文链接:https://blog.csdn.net/Lc1996Jm/article/details/51881064 一.引用: 1.建立一个Wi ...
- [学习笔记] 平衡树——Treap
前置技能:平衡树前传:BST 终于学到我们喜闻乐见的平衡树啦! 所以我们这次讲的是平衡树中比较好写的\(Treap\). (以后会写splay的先埋个坑在这) 好了,进入正题. step 1 我们知道 ...
- Laravel dingo,HTTP的请求头(accept)无法携带版本号的解决方法
Laravel dingo,HTTP的请求头(accept)无法携带版本号的解决方法 2017年9月6日 原创分享 zencodex 使用 Laravel dingo 做api开发时,涉及 A ...
- win10本机安装rabbitMQ
在win10环境下安装RabbitMQ的步骤 第一步:下载并安装erlang 原因:RabbitMQ服务端代码是使用并发式语言Erlang编写的,安装Rabbit MQ的前提是安装Erlang. 下载 ...
- CF990G GCD Counting 点分治+容斥+暴力
只想出来 $O(nlogn\times 160)$ 的复杂度,没想到还能过~ Code: #include <cstdio> #include <vector> #includ ...
- 关于windows 设备驱动重要的事实
1. windows采用设备树描述所有挂在系统总线上的设备,每个设备对应一个节点. 2.每个设备有自己的device object stack/driver stack. 一个物理上的设备对应多个de ...
- Centos安装成功后配置网络
一.设置IP地址.网关DNS 说明:CentOS 7.0默认安装好之后是没有自动开启网络连接的! cd /etc/sysconfig/network-scripts/ #进入网络配置文件目录 vi i ...
- Inter IPP 绘图 ippi/ipps
IPP的资料网上比较少,主要还是参考Inter官网和文档 官方文档ipps.pdf主要是对数据做处理,包括加减乘除.FFT.DFT等 文档ippi.pdf只要是对图像做处理,包括通道转换.图片处理等 ...
- 在CentOS 7上搭建WordPress
环境(ECS阿里云服务器) 服务器操作系统:CentOS 7.3 : 博客部署服务器:Apache HTTP: 数据库:MySql: 框架:WordPress: 步骤 一.安装 Apache HTTP ...
- java拦截器获取请求完整参数
public class OptLogAspect implements HandlerInterceptor { @Override public boolean preHandle(HttpSer ...