一、打家劫舍
题目一:198. 打家劫舍
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
dp[i]
表示到第i
间房屋时能偷窃到的最高金额动态规划方程如下:
dp[i] = max(dp[i-1], dp[i-2] + nums[i])
,其中nums[i]
是第i
间房屋中的金额
dp[i-1]
代表不偷当前房屋时的最大金额
dp[i-2] + nums[i]
代表偷当前房屋(并加上偷窃到第i-2
间房屋时的金额)的总金额
/*
* @lc app=leetcode.cn id=198 lang=cpp
*
* [198] 打家劫舍
*/
// @lc code=start
class Solution {
public:
int rob(vector<int>& nums) {
if (nums.empty()) return 0;
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-1], dp[i-2] + nums[i]);
}
return dp.back();
}
};
// @lc code=end
题目二:213. 打家劫舍 II
你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。
给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。
一次考虑不包括最后一间房屋,另一次考虑不包括第一间房屋
/*
* @lc app=leetcode.cn id=213 lang=cpp
*
* [213] 打家劫舍 II
*/
// @lc code=start
class Solution {
public:
int robLine(vector<int>& nums, int start, int end) {
int prev = 0, curr = 0;
for (int i = start; i < end; ++i) {
int temp = max(curr, prev + nums[i]);
prev = curr;
curr = temp;
}
return curr;
}
int rob(vector<int>& nums) {
int n = nums.size();
if (n == 1) return nums[0];
if (n == 2) return max(nums[0], nums[1]);
return max(robLine(nums, 0, n - 1), robLine(nums, 1, n));
}
};
// @lc code=end
题目三:337. 打家劫舍 III
小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 root
。
除了 root
之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 两个直接相连的房子在同一天晚上被打劫 ,房屋将自动报警。
给定二叉树的 root
。返回 在不触动警报的情况下 ,小偷能够盗取的最高金额 。
定义一个辅助函数来实现这个逻辑。这个辅助函数对于每个节点返回一个大小为2的数组,其中第一个元素表示不偷当前节点能得到的最大金额,第二个元素表示偷当前节点能得到的最大金额
/*
* @lc app=leetcode.cn id=337 lang=cpp
*
* [337] 打家劫舍 III
*/
// @lc code=start
/**
* 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) {
auto result = robSub(root);
return max(result[0], result[1]);
}
private:
vector<int> robSub(TreeNode* node) {
if (!node) return {0, 0};
auto left = robSub(node->left);
auto right = robSub(node->right);
int rob = node->val + left[0] + right[0];
int notRob = max(left[0], left[1]) + max(right[0], right[1]);
return {notRob, rob};
}
};
// @lc code=end