题目
动态规划
动态规划的四个解题步骤是;
- 定义子问题
- 写出子问题的递推关系
- 确定DP数组的计算顺序
- 空间优化(可选)
步骤一:定义子问题
子问题和原问题相似,但规模较小。本题中的子问题就是“从k个房子中能偷到的最大金额”,用f(k)表示
步骤二:写出子问题的递推关系
假设一共有n个房子,每个房子的金额分别是H0,H1,…Hn-1,子问题f(k)表示从前k个房子(即H0,H1,…Hk-1)中能偷到的最大金额。那么,偷k个房子有两种偷法:
k个房子中最后一个房子是Hk-1,如果不偷这个房子,那么问题就变成在前k-1个房子中偷盗的最大的金额,也就是子问题f(k-1)。如果偷这个房子,那么前一个房子Hk-2就不能偷,其他的房子不受影响。那么问题就变成在前 k-2k−2 个房子中偷到的最大的金额。两种情况中,选择金额较大的一种结果。
步骤三:确定DP数组的计算顺序
每个 f(k) 依赖 f(k-1) 和 f(k-2)。也就是说,dp[k] 依赖 dp[k-1] 和 dp[k-2],如下图所示。
DP 数组中的依赖关系都是向右指的,DP 数组的计算顺序就是从左向右。这样我们可以保证,计算一个子问题的时候,它所依赖的那些子问题已经计算出来了。
class Solution:
def rob(self, nums: List[int]) -> int:
if len(nums)==0: return 0
dp=[0 for _ in range(len(nums)+1)]
dp[0]=0
dp[1]=nums[0]
for k in range(2, len(nums)+1):
dp[k]=max(dp[k-1], nums[k-1]+dp[k-2])
return dp[len(nums)]
class Solution {
public:
int rob(vector<int>& nums) {
if(nums.size()==0){
return 0;
}
if (nums.size()==1){
return nums[0];
}
int l=nums.size();
vector<int> dp(l, 0);
dp[0]=nums[0];
dp[1]=max(dp[0], nums[1]);
for (int i=2; i<l; i++){
dp[i]=max(dp[i-1], dp[i-2]+nums[i]);
}
return dp[l-1];
}
};