代码随想录算法训练营第四十八天|打家劫舍专题

目录

LeeCode 198.打家劫舍

LeeCode 213.打家劫舍II

LeeCode 337.打家劫舍 III


LeeCode 198.打家劫舍

198. 打家劫舍 - 力扣(LeetCode)

动归五部曲

1.确定dp数组及下标含义: dp[i]: 考虑下标i(包括i)以内的房屋,最多可以偷窃的金额;

2.确定递推公式: dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);

3.dp数组如何初始化:dp[0] = nums[0]; dp[1] = max(nums[0], nums[1]);

4.确定遍历顺序:从前到后遍历;

5.举例递推dp数组;

代码:

class Solution {
public:
    int rob(vector<int>& nums) {
    	if (nums.size() == 0) return 0;
		if (nums.size() == 1) return nums[0];
		vector<int> dp(nums.size());
		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];
    }
};

时间复杂度: O(n)                      空间复杂度:O(n) 


LeeCode 213.打家劫舍II

213. 打家劫舍 II - 力扣(LeetCode)

思路:

相较于 LeeCode 198.打家劫舍 ,本题条件限制首尾房屋相连,可以分成两种情况讨论——考虑包含首元素,不包含尾元素 / 考虑包含尾元素,不包含首元素。(考虑不代表一定选中)

代码:

class Solution {
public:
    int rob(vector<int>& nums) {
    	if (nums.size() == 0) return 0;
    	if (nums.size() == 1) return nums[0];
    	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) {
    	if (end == start) return nums[start];
    	vector<int> dp(nums.size());
    	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];
	}
};

时间复杂度: O(n)                      空间复杂度:O(n) 


LeeCode 337.打家劫舍 III

337. 打家劫舍 III - 力扣(LeetCode)

动归五部曲

1.确定dp数组及下标含义: dp数组是长度为2的数组,在递归过程中,系统栈会保存每一层递归的参数,因此dp数组可以标记树中每个节点的状态;dp[i]: 下标为0记录不偷该节点所得到的的最大金钱,下标为1记录偷该节点所得到的的最大金钱;

2.确定递推公式: dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);

3.dp数组如何初始化:if (cur == NULL) return vector<int>{0, 0};

4.确定遍历顺序:后序遍历;

5.举例递推dp数组;

代码:

class Solution {
public:
    int rob(TreeNode* root) {
    	vector<int> result = robTree(root);
    	return max(result[0], result[1]);
    }
    vector<int> robTree(TreeNode* cur) {
    	if (cur == NULL) 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};
	}
};

时间复杂度: O(n)                      空间复杂度:O(log n) 

猜你喜欢

转载自blog.csdn.net/weixin_74976519/article/details/131133581