LeetCode:337 打家劫舍 III 暴力与动态规划

题目描述

打家劫舍I

在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。 除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。

计算在不触动警报的情况下,小偷一晚能够盗取的最高金额。

在这里插入图片描述

在这里插入图片描述

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/house-robber-iii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

这个小偷这么聪明为啥还要偷东西

暴力解:最直观的思路

递归地定义一个函数,叫 “偷” ,即返回在给定节点为根的树中,偷得的最大价值,下面的“偷”都是指调用这个函数

  1. 如果当前节点root只有左孩子,那么有两种偷法:
    1.偷root,+ 偷root左孩子的两个孩子
    2.偷root的左孩子
    返回大的结果作为偷root最大收益
    在这里插入图片描述
  2. 只有右孩子同上操作
  3. 如果同时具有左右孩子,那么还是两种偷法
    1.偷root和左右孩子的所有孩子
    2.偷root的左右孩子
    返回最大的值作为答案
    在这里插入图片描述

注意边界条件是空节点,偷的价值为0,直接return 0

代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int rob(TreeNode* root)
    {
        if(!root) return 0;
        if(!root->left && !root->right) return root->val;
        if(root->left && !root->right) 
            return max(root->val+rob(root->left->left)+rob(root->left->right), rob(root->left));
        if(!root->left && root->right)
            return max(root->val+rob(root->right->left)+rob(root->right->right), rob(root->right));
        return max(root->val
            +rob(root->left->left)+rob(root->left->right)
            +rob(root->right->left)+rob(root->right->right)
            , rob(root->left)+rob(root->right));
    }
};

动态规划

由上面的暴力递归不难看出状态转移,那么就好用dp了

递归是自顶向下的,而动态规划是满足自底向上,即先求解子问题

对树后序遍历可以完美地满足:先解子问题,在解问题的要求,可以直接把问题的解保存在树的值里面,使用常数的额外空间

递归地定义函数 lrd(root) ,将以root为根的树的偷得的最大价值保存在root节点的val中

代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
	// 查询节点值,遇到空返回0,方便处理递归边界
    int v(TreeNode*& root)
    {
        if(!root) return 0;
        return root->val;
    }
    void lrd(TreeNode*& root)
    {
        if(!root) return;
        // 先求解子问题
        lrd(root->left);
        lrd(root->right);
        // 状态转移
        if(root->left && !root->right)
            root->val = max(root->val+v(root->left->left)+v(root->left->right), root->left->val);
        else if(!root->left && root->right)
            root->val = max(root->val+v(root->right->left)+v(root->right->right),root->right->val);
        else if(root->left && root->right)
            root->val = max(root->val+v(root->left->left)+v(root->left->right)+v(root->right->left)+v(root->right->right), root->left->val+root->right->val);
    }
    int rob(TreeNode* root)
    {
        if(!root) return 0;
        lrd(root);
        return root->val;
    }
};
发布了199 篇原创文章 · 获赞 7 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44176696/article/details/104631306
今日推荐