198.打家劫舍
这道题还挺简单的,有点像前面的爬楼梯,dp[i]表示到第i个房间时能拿到的最多的钱是多少,dp[i]=max(dp[i-2]+nums[i],dp[i-1]),假设在第i个房间抢钱,那么获得的钱就是dp[i-2]+nums[i],假设在第i个房间不抢钱,那么获得的钱就是dp[i-1]。那要如何初始化呢,我们就先要初始dp[0]和dp[1],dp[0]因为只有一个房间,那必须抢,所以dp[0]=nums[0],而dp[1]就要考虑是抢第一个房间还是第二个房间了,也就是nums[0]和nums[1]中选择大的那一个。这道题还有一个坑点,就是假设nums的长度是1,那么dp【1】就没有意义了,因为dp[1]是在nums[0]和nums[1[中选一个,而nums只有一个数字,那dp[1]非法就会报错,所以我们得先判断!!!!
https://leetcode.cn/problems/house-robber/description/
class Solution {
public:
int rob(vector<int>& nums) {
if (nums.size() == 1) return nums[0];
vector<int>dp(nums.size(),0);
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];
}
};
213.打家劫舍II
这道题相比打家劫舍多了一个首尾相连,我一看环的问题我就不会,然后看了视频,发现是要分类讨论,一共就三种,一种是首尾都不抢劫,一种是抢劫首,一种是抢劫尾,而第一种其实已经包含在第二种和第三种的情况里面了,那么其实我们只需要把nums分成两部分传入打家劫舍的思路就行,一部分是没有尾,一部分是没有首,然后找两部分dp[end]的最大值。
https://leetcode.cn/problems/house-robber-ii/description/
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 result1=robRange(nums,0,nums.size()-2);
int result2=robRange(nums,1,nums.size()-1);
return max(result1,result2);
}
int robRange(vector<int>& nums, int start, int end)
{
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];
}
};
377.打家劫舍III
好家伙,打家劫舍已经演化成二叉树了,这道题的视频我看了三次,现在大概可以算懂了,这个是树和动态规划的结合,因为对于每一个节点,它有两种状态,一种是偷,一种是不偷,那如果偷了的话,得到的金钱=left[0]+right[0]+p->value,left[0]为左孩子不偷得到的金钱,right[0]为右孩子不偷得到的金钱,p->value为现在的节点偷了得到的金钱。那如果不偷的话,就是左右孩子金钱的总和的最大值,左孩子和右孩子可偷可不偷,只要把他们得到的金钱数相加即可。遍历顺序为后序,先遍历左右孩子,再一步步把结果返回给上一级。
https://leetcode.cn/problems/house-robber-iii/
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int rob(TreeNode* root) {
vector<int>result=robTree(root);
return max(result[0],result[1]);
}
vector<int>robTree(TreeNode*p)
{
if(p==NULL)
return vector<int>{0,0};
vector<int>left=robTree(p->left);
vector<int>right=robTree(p->right);
int value1=max(left[0],left[1])+max(right[0],right[1]);
int value2=p->val+left[0]+right[0];
return vector<int>{value1,value2};
}
};