LC “打家劫舍”系列问题

针对Byte Dance某一次面试的算法题目(LC 337. 打家劫舍 III ),现做如下整理。

目录

声明:以下“选”和“劫取”是同义词,自由替换

LC 198. 打家劫舍
思路

对于每一所房子有两种状态,要么选择,要么不选择,使用dp[i]记录当前位置房子所能劫取到的最大价值,即有:dp[i] = max(dp[i - 1], dp[i - 2] + nums[i])

代码
const int N = 105;
class Solution {
public:
    int dp[N];
    int rob(vector<int>& nums) {
        int n = nums.size();
        if (n == 0) return 0;
        if (n == 1) return nums[0];
        dp[0] = nums[0];
        dp[1] = max(dp[0], nums[1]); // 两种选择,要么劫取1,2不劫取;要么劫取2,1不劫取
        for (int i = 2; i < n; i ++ ) dp[i] = max(dp[i - 1], dp[i - 2] + nums[i]);
        return dp[n - 1];
    }
};

LC 213. 打家劫舍 II
思路

将问题划得分:

  • 第一座房子选择偷,那么最后一座房子一定不能偷,此时计算0 ~ n - 2,由dp[n - 2]得到当前方案最大值
  • 第一座房子不偷,最后一座房子可偷可不偷(反正可以偷,那就计算上),此时计算1 ~ n - 1,由dp[n - 1]取得当前方案最大值

递推式和打家劫舍I的一致,最后两种方案各自最优情况取最大值即可。

代码
const int N = 105;
class Solution {
public:
    int dp[N];
    int rob(vector<int>& a) {
        int n = a.size();
        // 情况特判
        if (n == 1) return a[0];
        else if (n == 2) return max(a[0], a[1]);
        
        dp[0] = a[0]; // 第一家要偷,最后一家不能偷:0~n-2
        dp[1] = max(dp[0], a[1]);
        for (int i = 2; i < n - 1; i ++ ) dp[i] = max(dp[i - 2] + a[i], dp[i - 1]);
        int ans = dp[n - 2];
        dp[0] = 0; // 第一家不偷,最后一家看情况:0~n-1
        dp[1] = a[1];
        dp[2] = max(a[2], dp[1]);
        for (int i = 3; i < n; i ++ ) dp[i] = max(dp[i - 2] + a[i], dp[i - 1]);
        ans = max(dp[n - 1], ans);
        return ans;
    }
};

LC 337. 打家劫舍 III
思路

针对某个节点(将其视为root考虑),若选择了该节点那么f[root, 1] = f[left, 0] + f[right, 1] + nums[i](其中0代表不选,1代表选);若不选该节点那么f[root, 0] = max(f[left, 0], f[right, 1]) + max(f[right, 0], f[left, 1])

代码
/**
 * 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:

    vector<int> dfs(TreeNode* u) {
        if (!u) return {0, 0};
        vector<int> x = dfs(u->left), y = dfs(u->right);
        return {max(x[0], x[1]) + max(y[0], y[1]), x[0] + y[0] + u->val};
    }

    int rob(TreeNode* root) {
        if (!root) return 0;
        vector<int> f = dfs(root);
        return max(f[0], f[1]);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

水能zai舟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值