代码随想录算法训练营第34天|198.打家劫舍、213.打家劫舍II、337.打家劫舍 III

LeetCode198

2025-03-07 17:08:07 星期五

题目描述:力扣198
文档讲解:代码随想录(programmercarl)198.打家劫舍
视频讲解:《代码随想录》算法视频公开课:动态规划,偷不偷这个房间呢?| LeetCode:198.打家劫舍

记录

刚开始看这个题意,自己先写了这样的代码,把下标为0和下标为1的数,操作语句为i += 2的所有数都加了起来,之后二者比个大小。70个测试用例过了40了

class Solution {
public:
	int rob(vector<int>& nums) {
		int sum1 = 0, sum2 = 0;
		for (int i = 1; i < nums.size(); i += 2) {
			sum1 += nums[i];
		}
		for (int i = 0; i < nums.size(); i += 2) {
			sum2 += nums[i];
		}
		return max(sum1, sum2);
	}
};

直到后面出现了[2,1,1,2]这个用例

代码随想录视频内容简记

梳理

  1. 确定dp[i]数组的含义,表示考虑到下标i(包含i)的能偷的最大金币数量为dp[i]。要明确这里的dp[i]不一定就是一定要偷第i个位置,只是考虑到了第i个位置

  2. 确定递推公式,首先是偷第i个房间,dp[i - 2] + nums[i],如果是不偷第i个房间,那么就是dp[i - 1]即可,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数组

LeetCode测试

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

LeetCode213

题目描述:力扣213
文档讲解:代码随想录(programmercarl)213.打家劫舍II
视频讲解:《代码随想录》算法视频公开课:动态规划,房间连成环了那还偷不偷呢?| LeetCode:213.打家劫舍II

代码随想录视频内容简记

这道题和打家劫舍Ⅰ的区别就在于本题是一个环形的结构,那他的思路就是把一个环展开成一个线性结构,之后直接套用就可以了

动归五部曲和上面的一样,就是包含了几种情况

情况一,不考虑首元素和尾元素,只考虑中间元素

情况二,考虑首元素和中间元素,不考虑尾元素

情况三,考虑尾元素和中间元素,不考首元素

注意:其中情况一可以包含在任意情况二或者情况三中

LeetCode测试

这个题主要就是细节多,好多测试用例过不了。主要把size = 0,1,2三种的单独写出来,才能进行数组的截取,否则很容易出现数组越界

点击查看代码
class Solution {
private:
    int robone(vector<int>& nums, int start, int end) {
        int size = end - start + 1;
        vector<int> dp(size + 1, 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 - 1], dp[i - 2] + nums[i]);
        }
        return dp[end];
    }

public:
    int rob(vector<int>& nums) {
        if (nums.size() == 0) return 0;
        if (nums.size() == 1) return nums[0];
        if (nums.size() == 2) return max(nums[0], nums[1]);
        int case1 = robone(nums, 0, nums.size() - 2);
        int case2 = robone(nums, 1, nums.size() - 1);
        return max(case1, case2);
    }
};

LeetCode337

题目描述:力扣337
文档讲解:代码随想录(programmercarl)337.打家劫舍 III
视频讲解:《代码随想录》算法视频公开课:动态规划,房间连成树了,偷不偷呢?| LeetCode:337.打家劫舍3

代码随想录视频内容简记

本题是一道二叉树和动态规划结合的题目,树形dp。接下来还是按照二叉树递归遍历的思路进行分析,感觉还是很不好想的

梳理

  1. 确定函数的参数和返回值

  2. 确定递归的终止条件

  3. 确定单层递归的逻辑

大致代码内容

  1. 确定vector<int> robtree(TreeNode* cur),这道题目返回的是一个vector数组,包括两个状态,分别是当前结点不偷所获得的最大金额,还有当前结点偷所能获得最大金额。也就是本题的dp数组就只有两个长度

  2. 确定递归的终止条件,if (cur == NULL) return {0, 0};

  3. 确定单层递归的逻辑。首先定义vector<int> leftdp = robtree(cur->left);vector<int> rightdp = robtree(cur->right);

    1. 确定dp数组的含义,定义两个val1和val2,也就是本题中的dp分别表示不偷和偷的最大金额数量

    2. 确定递推公式。

    如果偷当前结点(比如上图的3),那么说明左右孩子都不能偷,val1 = cur->val + leftdp[0] + rightdp[0]

    如果不偷当前结点,那么就可以从左右孩子结点的偷和不偷的状态中找到最大值,也就是val2 = max(leftdp[0], leftdp[1]) + max(rightdp[0], rightdp[1])

    最后return {val2, val1}即可

    1. dp数组初始化,已经在递归的终止条件中写好了

    2. 确定递归的遍历顺序,本题用的是后序遍历,需要父结点获得将左子树和右子树的最大金额进行

    3. 打印dp数组

LeetCode测试

点击查看代码
/**
 * 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* cur) {
        if (cur == NULL) return {0, 0};
        vector<int> leftdp = robtree(cur->left);
        vector<int> rightdp = robtree(cur->right);
        int val1, val2;// val1表示偷,val2表示不偷
        val1 = cur->val + leftdp[0] + rightdp[0];
        val2 = max(leftdp[0], leftdp[1]) + max(rightdp[0], rightdp[1]);
        return {val2, val1};
    }

public:
    int rob(TreeNode* root) {
        vector<int> result = robtree(root);
        return max(result[0], result[1]);
    }
};
posted on   bnbncch  阅读(214)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示