class Solution {
public:
int rob(vector<int>& nums) {
vector<int> dp(nums.size() + 1, 0);
nums.insert(nums.begin(), 0);
dp[1] = nums[1];
int pre = 1;
for (int i = 2; i < dp.size(); i++){
if (pre == (i - 1)){
if (dp[i - 1] < dp[i - 2] + nums[i]){
dp[i] = dp[i - 2] + nums[i];
pre = i;
}else{
dp[i] = dp[i - 1];
}
}else{
dp[i] = dp[i - 1] + nums[i];
pre = i;
}
}
for(int i=0;i<nums.size();i++){
cout<<dp[i]<<" ";
}
return dp[nums.size() - 1];
}
};
这题笔者一开始没看题解,有些想得太复杂了,考虑了上一个打劫的是不是与当前位置相邻,看了题解之后发现其实不需要知道是否相邻,dp[i-2]打劫的不会与i相邻,而dp[i-1]可能与打劫过的可能与i相邻,所以只需要取dp[i-1]与dp[i-2]+nums[i]两者的最大值即可。
class Solution {
private:
int robrange(vector<int> nums, int start, int end){
vector<int> dp(nums.size(), 0);
dp[start] = nums[start];
for (int i = start + 1; i < end; i++){
dp[i] = max(dp[i - 1], dp[i - 2] + nums[i]);
}
return dp[end - 1];
}
public:
int rob(vector<int>& nums) {
if (nums.size() == 1) return nums[0];
nums.insert(nums.begin(), 0);
int result1 = robrange(nums, 1, nums.size()-1);
int result2 = robrange(nums, 2, nums.size());
return max(result1, result2);
}
};
这题一开始笔者以为或许会给出一种只需遍历一遍即可的方案,看了题解之后发现就是一次掐头一次去尾,遍历两次取最大值。
/**
* 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 {
private:
vector<int> robtree(TreeNode* root){
if (root == NULL) return {0, 0};
vector<int> left = robtree(root->left);
vector<int> right = robtree(root->right);
vector<int> result(2, 0);
result[0] = left[1] + right[1] + root->val;
result[1] = max(left[0], left[1]) + max(right[0], right[1]);
return result;
}
public:
int rob(TreeNode* root) {
vector<int> result = robtree(root);
return max(result[0], result[1]);
}
};
这题难的地方在于一个节点可能有3个邻接,就不能再用之前的方法了。随想录给的题解是自底向上,求取对当前节点来说,打劫与不打劫的最大值,在递归中,每个节点会向上传递两个值,一个是打劫当前节点的最大值,一个是不打劫当前节点的最大值,前者意味着不能打劫左右子节点,所以直接利用子节点得出的不打劫子节点的最大值计算,后者代表子节点可以被打劫也可以不被打劫,比对子节点得出的被打劫与不被打劫的最大值计算即可,一次类推,即可得到答案。