Leetcode 337. 打家劫舍Ⅲ 树形dp C++实现

问题:Leetcode 337. 打家劫舍Ⅲ

小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 root 

除了 root 之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 两个直接相连的房子在同一天晚上被打劫 ,房屋将自动报警。

给定二叉树的 root 。返回 在不触动警报的情况下 ,小偷能够盗取的最高金额 。

/**
 * 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) {}
 * };
 */

算法:

        和之前做过的Leetcode 198. 打家劫舍类似,选了当前结点就不能选与之相连的结点了。

这里我们分成两种情况,当前节点 或者 不选 。需要考虑几个点,结点是否为空?如果选了当前结点 node ,那就不能选他的 两个儿子结点(node -> left , node -> right)。

在每次递归时,我们要 return 两种情况,选 或者 不选。即 1、选当前节点 2、不选当前节点,取左右儿子的最大值。

时间复杂度:O(n) ,其中 n 为二叉树的节点个数。每个节点都会递归恰好一次。
空间复杂度:O(n) 。最坏情况下,二叉树是一条链,递归需要 O(n) 的栈空间。

代码:

class Solution {
    pair<int,int>dfs(TreeNode *node){
        if(!node)   return {0,0};// 递归边界,没有节点,怎么选都是 0
        auto [l_rob,l_not_rob] = dfs(node->left); // 递归左子树
        auto [r_rob,r_not_rob] = dfs(node->right); // 递归右子树
        int rob = l_not_rob + r_not_rob + node->val; // 选
        int not_rob = max(l_rob,l_not_rob) + max(r_rob,r_not_rob); // 不选
        return {rob,not_rob};
    }

public:
    int rob(TreeNode* root) {
        auto[root_rob,root_not_rob] = dfs(root);
        return max(root_rob,root_not_rob); // 根节点选或不选的最大值
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值