LeetCode 337 House Robber III

174 阅读2分钟

LeetCode 337 House Robber III

思路

本题要求tree中相邻node有限制条件,是此类题目的典型。

  1. 不知道当前节点是否被使用,且在向下递归的过程中,之前节点是否被使用过的信息会丢失,因此,在参数中传递一个used参数,保存此信息。used为true,说明使用了root节点,否则,没使用root节点。当使用root节点时,root的两个子节点不能使用,当没使用root节点时,两个子节点可用可不用。

  2. 与第一种方法大同小异,只不过每次递归时,将使用root和不使用root两种情况都检查了,然后返回最大值。返回的结果总是符合相邻节点间的限制,因此不会在返回递归时,不会违背该限制。

  3. 前两种方法通过unordered_map防止超时。第三种方法通过传引用的方式提速。事实证明,很多时候通过传引用的方式,表现更好。

代码

方法1

class Solution {
public:
    int rob(TreeNode* root) {
        unordered_map<TreeNode*, int> useMap;
        unordered_map<TreeNode*, int> unUseMap;
        return max(DFS(root, true, useMap, unUseMap), DFS(root,false, useMap, unUseMap));
    }
    
    int DFS (TreeNode* root, bool used, unordered_map<TreeNode*, int> &useMap, unordered_map<TreeNode*, int> &unUseMap) {
        if (!root) return 0;
        int useLeft = 0, useRight = 0, unUseLeft = 0, unUseRight = 0;
        
        if (useMap.count(root->left))
            useLeft = useMap[root->left];
        else {
            useLeft = DFS(root->left, true, useMap, unUseMap);
            useMap[root->left] = useLeft;
        }
        
        if (useMap.count(root->right))
            useRight = useMap[root->right];
        else {
            useRight = DFS(root->right, true, useMap, unUseMap);
            useMap[root->right] = useRight;
        }
        
        if (unUseMap.count(root->left))
            unUseLeft = unUseMap[root->left];
        else {
            unUseLeft = DFS(root->left, false, useMap, unUseMap);
            unUseMap[root->left] = unUseLeft;
        }
        
        if (unUseMap.count(root->right))
            unUseRight = unUseMap[root->right];
        else {
            unUseRight = DFS(root->right, false, useMap, unUseMap);
            unUseMap[root->right] = unUseRight;
        }
        
        
        if (used)
            return root->val + unUseLeft + unUseRight;
        else
            return max(useLeft, unUseLeft) + max(useRight, unUseRight);
    }
};

### 方法2

class Solution {
public:
    int rob(TreeNode* root) {
        unordered_map<TreeNode*, int> mp;
        
        return rob(root, mp);
        
    }
    
    int rob (TreeNode *root, unordered_map<TreeNode*, int> &mp) {
        if (!root) return 0;
        if (mp.count(root)) return mp[root];
        
        int sum = 0;
        
        if (root->left) 
            sum += rob(root->left->left, mp) + rob(root->left->right, mp);

        if (root->right)
            sum += rob(root->right->left, mp) + rob(root->right->right, mp);
        
        sum = max(sum + root->val, rob(root->left, mp) + rob(root->right, mp));
        mp[root] = sum;
        
        return sum;
    }
};

方法3

class Solution {
public:
    int rob(TreeNode* root) {
        int withMe, withoutMe;

        withMe = withoutMe = 0;
        maxMoney(root, withMe, withoutMe);
        return max(withMe, withoutMe);
    }
    
    void maxMoney(TreeNode* root, int &withMe, int &withoutMe) {
        int wMeL, woMeL; // max money robbed: (with/without me for left child)
        int wMeR, woMeR; // max money robbed: (with/without me for right child)

        if (!root)
            return;
        wMeL = woMeL = wMeR = woMeR = 0;
        maxMoney(root->left, wMeL, woMeL);
        maxMoney(root->right, wMeR, woMeR);
        withMe = woMeL + woMeR + root->val;
        withoutMe = max(wMeL, woMeL) + max(wMeR, woMeR);
    }
};