• Leetcode(337)-打家劫舍III


    小偷又发现一个新的可行窃的地点。 这个地区只有一个入口,称为“根”。 除了根部之外,每栋房子有且只有一个父房子。 一番侦察之后,聪明的小偷意识到“这个地方的所有房屋形成了一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。

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

    示例 1:

         3
        / 
       2   3
            
         3   1
    

    能盗取的最高金额 = 3 + 3 + 1 = 7.

    示例 2:

         3
        / 
       4   5
      /     
     1   3   1
    

    能盗取的最高金额 = 4 + 5 = 9.

    思路:这次是在树形结构中找不能相邻的最大金额数。首先我们可以这样想,对于每个节点,我们都可以进行选与不选两种方案,如果选,那么意味着它的左右节点不能被选,如果不选,也不是意味着我必须要选它的左右节点,还要接着判断左右节点是选还是不选。

    class Solution {
    public:
        int rootexclude(TreeNode* root)
        {
            if(root==NULL) return 0;
            return rob(root->left)+rob(root->right);
        }
        int rootinclude(TreeNode* root)
        {
            if(root==NULL) return 0;
            return rootexclude(root->left)+rootexclude(root->right)+root->val;
        }
        int rob(TreeNode* root) 
        {
            if(root==NULL) return 0;
            return max(rootinclude(root),rootexclude(root));
        }  
    };

    上述程序完美的体现了这个思想,其中rootinclude函数表示了将根节点选入,rootexclude函数表示不选根节点。我们最后回溯,只需要搞清楚对于整个二叉树的根节点来说,我是选还是不选,就可以得到最后的结果。

    当然了,上述算法的时间复杂度并不低,因为三个函数互相调用递归的成本太大,有大神提出了动态规划的解法。

    class Solution {
            int walk(TreeNode* root,int&val)
            {
                val=0;
                if(root==NULL)
                    return 0;
                int left,right;
                val=walk(root->left,left)+walk(root->right,right);
                return max(val,left+right+root->val);   
          }
    public:
        int rob(TreeNode* root) {
            int val;
            return walk(root,val);//这里采用引用传参的方式记录决策路径
        }
    };
  • 相关阅读:
    c++跨平台技术学习(一)--使用公共的代码
    软件项目将死的27个征兆
    Java中的方法重载应用
    Java成员变量的初始化和在內存中的运行机制
    Java源文件结构和Java常用包
    细说Java访问控制符
    构造函数与this
    linux基础学习-6.3-DNS的配置文件
    linux基础学习-6.2-网卡配置文件
    linux基础学习-6.1-目录结构的特点
  • 原文地址:https://www.cnblogs.com/mini-coconut/p/9402699.html
Copyright © 2020-2023  润新知