98.打家劫舍
题目
我是一个小偷,不能连着两家偷东西,问我能偷的最大价值?
dp[i]的含义是到第i家时偷的最大金额
dp[i]=max(dp[i-2]+value[i],dp[i-1])
注意dp[i-1]并不意味着一定偷i-1,只是在不偷i时,考虑前i-1个房间。
class Solution {
public:
int rob(vector<int>& nums) {
if(nums.size()==1)
return nums[0];
vector<int> dp(nums.size());
dp[0]=nums[0];
dp[1]=max(nums[0],nums[1]);
for(int i=2;i<nums.size();i++){
dp[i]=max(dp[i-2]+nums[i],dp[i-1]);
}
return dp[nums.size()-1];
}
};
太ez了哥们,
213.打家劫舍II
题目
现在变成环形小区了,唯一变的就是怎么处理这个环。
可以直接不考虑第一个小区来一次,再来一个不考虑最后一个来一次,挑个最大的。
class Solution {
public:
int rob(vector<int>& nums) {
if(nums.size()==1)
return nums[0];
if(nums.size()==2)
return max(nums[0],nums[1]);
int n=nums.size();
vector<int> dp1(n-1,0);
dp1[0]=nums[0];
dp1[1]=max(nums[1],nums[0]);
for(int i=2;i<n-1;i++){
dp1[i]=max(dp1[i-2]+nums[i],dp1[i-1]);
}
vector<int> dp2(n-1,0);
dp2[0]=nums[1];
dp2[1]=max(nums[2],nums[1]);
for(int i=2;i<n-1;i++){
dp2[i]=max(dp2[i-2]+nums[i+1],dp2[i-1]);
}
return max(dp1[n-2],dp2[n-2]);
}
};
我嘞个分类讨论啊,没想到Carl也是这样做的,我还以为会用while来处理环呢。
337.打家劫舍 III
class Solution {
public:
int rob(TreeNode* root) {
if(root==NULL)
return 0;
if(root->left==NULL&&root->right==NULL)
return root->val;
int result1=rob(root->left)+rob(root->right);
int result2;
if(root->left==NULL&&root->right!=NULL)
result2=rob(root->right->right)+rob(root->right->left);
else if(root->left!=NULL&&root->right==NULL)
result2=rob(root->left->right)+rob(root->left->left);
else{
result2=rob(root->left->right)+rob(root->left->left)+rob(root->right->right)+rob(root->right->left);
}
result2+=root->val;
return max(result1,result2);
}
};
暴力搜索会超时,因为不取root->val,搜左孩子和右孩子时会搜到它们的子孙,而取了root直接搜子孙会有重复
记忆化递推
用map记录哪些节点是搜索过的,对于搜过的节点直接返回它的值。
if(map.find(root)!=map.end())
return map[root];
树形dp
动态规划其实就是使用状态转移容器来记录状态的变化,这里可以使用一个长度为2的数组,记录当前节点偷与不偷所得到的的最大金钱。
用一个数组vector dp记录,dp[0]是不偷当前位置,dp[1]是考虑偷当前位置。
如果不偷当前位置,就去偷他的左右孩子
当然要先把遍历左右孩子的金钱树,才能处理当前节点。
dp[0]=leftdp+rightdp
class Solution {
public:
vector<int> robTree(TreeNode* root){
if(root==NULL){
return {0,0};
}
vector<int> leftdp=robTree(root->left);
vector<int> rightdp=robTree(root->right);
vector<int> dp(2);
dp[0]=max(leftdp[0],leftdp[1])+max(rightdp[0],rightdp[1]);
dp[1]=root->val+leftdp[0]+rightdp[0];
return dp;
}
int rob(TreeNode* root) {
vector<int> result=robTree(root);
return max(result[0],result[1]);
}
};