zoukankan      html  css  js  c++  java
  • 解题思路:house robber i && ii && iii

    这系列题的背景:有个小偷要偷钱,每个屋内都有一定数额的钱,小偷要发家致富在北京买房的话势必要把所有屋子的钱都偷了,但是屋子之内装了警报器,在一定条件下会触发朝阳群众的电话,所以小偷必须聪明一点,才能保证偷到的钱最多。

    问题i:这些屋子排成一排,连续两家失窃就会触发朝阳群众电话

    问题ii:这些屋子两成一个圈(四合院既视感),连续两家失窃就会触发朝阳群众电话

    问题iii:这些屋子组成一棵树,有连接的两个节点同时失窃就会触发朝阳群众电话

    i: 思路:一道典型的dp问题,dp[i]表示在小偷路过第i间房子后可以获得的最大收益。小偷这个时候有两个选择,to steal or not to steal, that is a  problem。考虑到会报警的情况,如果第i-1间房子小偷没下手的话,那么 dp[i] = dp[i-1]+nums[i];如果第i-1间的房子小偷下手的话,那么dp[i] = dp[i-1],如果小偷想把自己的利益最大化,比如会有 dp[i] = max(dp[i-1]+nums[i],dp[i-1]),不对啊,这个怎么看都是前者比较大吧?其实还有个隐藏的细节在这里,如果第i-1间房子没有下手的话, dp[i-1] = dp[i-2]。所以dp的状态方程就变成dp[i] = max(dp[i-2]+nums[i],dp[i-1])。由于咱们实际上只需要3个变量就足以记录dp信息,所以就不用数组记录dp信息啦。

            
    int size = nums.size();
         if(size == 0) return 0; if(size == 1) return nums[0]; if(size == 2) return max(nums[0],nums[1]); int s1 = nums[0],s2 = max(nums[0],nums[1]),s3; for(int i = 2;i<size;i++){ s3 = max(s2,s1+nums[i]); s1 = s2;s2 = s3; } return s3;

    ii: 思路:给的仍然是一个数组,只是第一间房子和最后一间房子不能同时下手,其实仍然是问题i的变形而已,只要不同时取到第一间和最后一间就行啦。所以有两种情况,一个是我不考虑最后一间,即考虑从第1到第n-1间房子;另一个是我不考虑第一间,即考虑从第2到第n间的情况。然后比较这两种情况。

            int size = nums.size();
            if(size == 0) return 0;
            if(size == 1) return nums[0];
            if(size == 2) return max(nums[0],nums[1]);
            if(size == 3) return max(max(nums[0],nums[1]),nums[2]);
            vector<int> dp(size-1,0),dp2(size-1,0);
            int s1 = nums[0],s3 = nums[1],s2 = max(nums[1],nums[2]),s4 =  max(nums[2],nums[1]), s5,s6;
    
            
            for(int i = 2;i<size-1;i++){
                s5 = max(s1,s2+nums[i]);
                s6 = max(s3,s4+nums[i+1]);
                s1 = s2; s2 = s5;
                s3 = s4; s4 = s6;
            }
            
            return max(s5,s6);    
    

    iii:这道题的画风和i&&ii不太一样,感觉考察的是树的问题。我AC的解法效率不高,不过便于理解,用一个flag辅助判断,如果flag为1表示当前节点不能偷;如果flag为0,当前节点可以偷,但是小偷有两种选择,to steal or not to steal,这取决了会不会让利益最大化。所以用一个递归解决了。

    class Solution {
    public:
        int helper(TreeNode* root,bool flag){
            if(!root) return 0;
            if(flag) return helper(root->left,0)+helper(root->right,0);
            else return max(root->val+helper(root->left,1)+helper(root->right,1),helper(root->left,0)+helper(root->right,0));
        }
        int rob(TreeNode* root) {
            return helper(root,0);
        }
    };
    

      

  • 相关阅读:
    Firemonkey 控件设定字型属性及颜色
    ListView 使用 LiveBindings 显示超过 200 条记录
    Firemonkey ListView 获取项目右方「>」(Accessory) 事件
    XE7 Update 1 选 iOS 8.1 SDK 发布 iPhone 3GS 实机测试
    Firemonkey Bitmap 设定像素颜色 Pixel
    Firemonkey 移动平台 Form 显示使用 ShowModal 范例
    XE7 提交 App(iOS 8)提示「does not contain the correct beta entitlement」问题修复
    XE7 Android 中使用 MessageDlg 范例
    导出 XE6 预设 Android Style (*.style) 档案
    修正 Memo 設定為 ReadOnly 後, 無法有複製的功能
  • 原文地址:https://www.cnblogs.com/unclelin/p/6553670.html
Copyright © 2011-2022 走看看