"House Robber" and "House Robber III"

House Robber:

nums为{3, 2, 1, 5},那么dp[0]=3,dp[1]=3,得到递推公式dp[i] = max(num[i] + dp[i - 2], dp[i - 1]), 代码如下:

class Solution {
public:
    int rob(vector<int> &num) {
        if (num.size() <= 1) return num.empty() ? 0 : num[0];
        vector<int> dp = {num[0], max(num[0], num[1])};
        for (int i = 2; i < num.size(); ++i) {
            dp.push_back(max(num[i] + dp[i - 2], dp[i - 1]));//递推公式
        }
        return dp.back();
    }
};

House Robber III:

和上一个题的思路完全不一样,曾经被带偏去用广搜求树的每一层的和组成数组,然后像上面的题一样用动态规划。。。

这道题用深度优先搜索来解决。对于当前节点,只有盗窃和不盗窃两种操作,这取决于当前节点的子节点的状态,可用两个变量表示:not和yes:
not:当前节点(屋子)不偷盗时,所能获得的收益;取决于在该节点的两个子节点被偷盗时的收益之和。
yes:当前节点(屋子)偷盗时,所能获得的收益;由于相邻节点不能同时偷盗否则会引来警察,所以两个子节点不能偷盗,此时收益等于:父节点->val + 左子节点->not+ 右子节点->not。
比较两种收益not和yes,取较大者作为当前节点的最大收益。

class Solution {
public:
	struct Money {
		int not;  // 该节点不偷,收益为子节点偷的情况下的收益和
		int yes; // 该节点处偷,加上两子节点不偷时的收益
		Money() :not(0), yes(0) {}
	};

	int rob(TreeNode* root) {
		Money sum = dfs(root);
		return sum.yes;
	}

	Money dfs(TreeNode* root)
	{
		if (root == NULL) return Money();
		Money leftMoney = dfs(root->left);   // 当前节点的左子节点收益情况
		Money rightMoney = dfs(root->right); // 当前节点的右子节点收益情况
		Money sumMoney;
		sumMoney.not = leftMoney.yes + rightMoney.yes; // 当前节点不偷
		sumMoney.yes = max(sumMoney.not, root->val + leftMoney.not + rightMoney.not);
		return sumMoney;
	}
};
写完代码回过头来看,发现其实还是动态规划的问题,只不过数据结构从数组变成了树。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值