- 198.打家劫舍
- 213.打家劫舍II
- 337.打家劫舍III
第一题:打家劫舍
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
- 示例 1:
- 输入:[1,2,3,1]
- 输出:4
0、思路:站在房屋前,只考虑偷或者不偷,做选择的前提是考虑的是前一个房屋和前两个房屋是否被偷,因为要间隔的偷。-。-。-
1、动态规划三部曲
(1)确定dp数组以及下标的含义
dp[i]:考虑下标i(包括i)以内的房屋,最多可以偷窃的金额为dp[i]
(2)确定递推公式
dp[i]的的决定因素是第i间房偷不偷
如果偷:dp[i]=dp[i-2]+nums[i],因为第i-1房肯定不偷
如果不偷:dp[i]=dp[i-1],,不偷的话手里的钱就跟i-1房间时一样,i-1的时候也可能没偷,但是判断依据是相邻的房间
然后dp[i]取最大值:dp[i]=max(dp[i-2]+nums[i],dp[i-1])
(3)dp数组如何初始化
从递推公式dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);可以看出,递推公式的基础就是dp[0] 和 dp[1]
dp[0]一定是nums[0],dp[1]的取值来源于nums[0]和nums[1],选一个偷
dp[1]=max(nums[0],nums[1])
(4)确定遍历顺序
dp[i]既然取决于dp[i-1]和dp[i-2],那么一定是从前到后遍历
(5)举例推导
第二题:打家劫舍2
你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。
给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,能够偷窃到的最高金额。
示例 1:
-
输入:nums = [2,3,2]
-
输出:3
-
解释:你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2), 因为他们是相邻的。
0、思考
这里的房间变成了环状,也就是第一件房和最后一间房相邻。如果第一间房偷了,最后一间就不能偷,只能偷一个
有三种思考方式:(1)直接不考虑头和尾,(2)只考虑头,不考虑尾(3)只考虑尾,不考虑头
然后选取其中最大的
只是多了一步求最大情况,求最大金额的步骤还是一样
第三题:打家劫舍3
之前是一排数组,现在是一棵树,要求不能偷两个直接相连的房子。dp树
有树肯定有遍历,就看是前序遍历还是中序,后序。问题是直接相连的树不能偷,所以应该是后序遍历左右根,可以偷两个孩子,但是会他们直接相连的父节点不可以偷。
本题重点在于dp数组,dp数组是一个长度为2的数组,每次累计记录最大的值。