思路:最开始做的时候,有点被前几天的背包问题代入进去了,其实这道题是一个经典的动态规划的问题,其每个位置的状态与前面两个位置都有关系,其实大家可以联系一下746.使用最小花费爬楼梯这道题,本质的思路完全一样,每个位置,我只关心在该位置前两个位置的大小,与其他无关!故初始化
nums[0]
和nums[1]
是必须要进行初始化的!
class Solution {
public:
int rob(vector<int>& nums) {
if(nums.size()==0)return 0;
if(nums.size()==1)return nums[0];
//dp数组:表示第i个位置,偷窃到的最大金额
vector<int> dp(nums.size());
//初始化:一件物品都不偷的金额是0,即dp[0]=0
dp[0]=nums[0];
dp[1]=max(nums[0],nums[1]);
//递推公式:dp[i]=max(dp[i-2]+nums[i],dp[i-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];
}
};
思路:这道题的关键点将问题分成两个问题,分别求出最大的值,然后返回最大值!
class Solution {
public:
int rob(vector<int>& nums) {
if(nums.size()==0)return 0;
if(nums.size()==1)return nums[0];
int result1=myrob(nums,0,nums.size()-2);//考虑首,不考虑尾
int result2=myrob(nums,1,nums.size()-1);//考虑尾,不考虑首
return max(result1,result2);
}
int myrob(vector<int>& nums,int start,int end)
{
if(start==end)return nums[start];
vector<int> dp(nums.size(),0);
dp[start]=nums[start];
dp[start+1]=max(nums[start],nums[start+1]);
for(int i=start+2;i<=end;i++)
{
dp[i]=max(dp[i-2]+nums[i],dp[i-1]);
}
return dp[end];
}
};
思路:对于树形dp而言,dp数组的含义是每一层的两个数,第一个值表示选择该节点,另外一个值表示不选择该节点,还是要利用递归来求解。
class Solution {
public:
int rob(TreeNode* root) {
//只能从根节点进入
vector<int> result=robtree(root);
return max(result[0],result[1]);
}
vector<int> robtree(TreeNode* node)
{
if(node==nullptr)return vector<int>{0,0};
vector<int> left(2,0);
vector<int> right(2,0);
left=robtree(node->left);
right=robtree(node->right);
int val1=node->val+left[0]+right[0];
int val2=max(left[0],left[1])+max(right[0],right[1]);
return {val2,val1};
}
};