状态:Debug后AC。
没啥好说的,按照流程分析即可。代码如下:
class Solution {
public:
int rob(vector<int>& nums) {
/*
dp[i], 到i号房屋的最大收益
dp[i] = max(dp[i-2]+nums[i], dp[i-1])
dp[0] = 0, dp[1] = nums[0]
for(int i = 2; i < nums.size(); ++i)
[1, 2, 3, 1] dp[1] = 1 | dp[2] = (0+2, 1) = 2 | dp[3] = (1+3, 2) = 4 | dp[4] = (2+1, 4) = 4
*/
int len = nums.size();
if(len == 1) return nums[0];
vector<int> dp(len+1, 0);
dp[1] = nums[0];
for(int i = 2; i <= len; ++i){
dp[i] = max(dp[i-2]+nums[i-1], dp[i-1]);
}
return dp[len];
}
};
状态:查看思路后AC。
相较上题的变化就是变成了循环状态,分成三种状态:1. 不考虑头尾;2. 掐头;3.去尾。其中情况2和3包括了第一种情况,因为DP算法会根据情况考虑要不要加入开头(结尾)。其他部分和上一题一样,代码如下:
class Solution {
public:
int robRange(vector<int>& nums, int begin, int end){
if(begin == end) return nums[begin];
vector<int> dp(nums.size());
dp[begin] = nums[begin];
dp[begin+1] = max(nums[begin], nums[begin+1]);
for(int i = begin+2; i <= end; ++i){
dp[i] = max(dp[i-2] + nums[i], dp[i-1]);
}
return dp[end];
}
int rob(vector<int>& nums) {
int len = nums.size();
if(len == 1) return nums[0];
int res1 = robRange(nums, 1, len-1);
int res2 = robRange(nums, 0, len-2);
return max(res1, res2);
}
};
状态:不会。
动态规划数组,当前节点偷和不偷的最大收益(dp[2]),二叉树遍历方法:后续遍历。代码如下:
class Solution {
public:
int rob(TreeNode* root) {
vector<int> res = robTree(root);
return max(res[0], res[1]);
}
vector<int> robTree(TreeNode* cur){
// [偷,不偷]
if(cur == nullptr) return vector<int>{0, 0};
vector<int> left = robTree(cur->left);
vector<int> right = robTree(cur->right);
int val1 = cur->val + left[0] + right[0];
int val2 = max(left[0], left[1]) + max(right[0], right[1]);
return {val2, val1};
}
};