LeetCode -. 337 robberies III

After completion of the last lap after robbing a street and house, he discovered a thief can steal new areas. The region has only one entrance, which we call the "root." In addition to the "root", and only the houses a "parent" house associated therewith. After some reconnaissance, clever thief realized that "this place all the houses are arranged similar to a binary tree." If both houses are directly connected robbed the same night, the house alarm.

Calculated without touching the alarm, a thief can steal the maximum amount of night.

Example 1:

输入: [3,2,3,null,3,null,1]

     3
    / \
   2   3
    \   \ 
     3   1

输出: 7 
解释: 小偷一晚能够盗取的最高金额 = 3 + 3 + 1 = 7.

Example 2:

输入: [3,4,5,1,3,null,1]

     3
    / \
   4   5
  / \   \ 
 1   3   1

输出: 9
解释: 小偷一晚能够盗取的最高金额 = 4 + 5 = 9.

https://leetcode-cn.com/problems/house-robber-iii/

Recursion

This problem is typical of recursion, backtracking can be used to do, because the result before the current calculation relies, then for a certain node, if the left child node exists, by recursively calling the function, calculates the left child does not comprise value of the node returned by the same token, if the right child exists, does not include calculated value of the right child node to return,

Then the maximum value of this node may be two cases, one is the node does not include the return value plus a left child node and the right child nodes and values, the other is left child node and the return value does not include the current period node value, whichever is greater to return, but this method can not pass OJ, timed out, it is necessary to optimize this method,

This method of double counting a lot of places, such as to complete a compute node, we have been looking for about child node calculation, can already calculated that the node maintains a HashMap up after the recursive call time, now HashMap where to find, if a direct return, if not present, and so calculated, saved to the HashMap back, then calling so convenient later, see the following code:

c++

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

java

Map<TreeNode, Integer> memo = new HashMap<>();
public int rob(TreeNode root) {
    if (root == null) return 0;
    // 利用备忘录消除重叠子问题
    if (memo.containsKey(root)) 
        return memo.get(root);
    // 抢,然后去下下家
    int do_it = root.val
        + (root.left == null ? 
            0 : rob(root.left.left) + rob(root.left.right))
        + (root.right == null ? 
            0 : rob(root.right.left) + rob(root.right.right));
    // 不抢,然后去下家
    int not_do = rob(root.left) + rob(root.right);
    
    int res = Math.max(do_it, not_do);
    memo.put(root, res);
    return res;
}

Dynamic Programming

Next, look at a method, this method is a recursive function returns the size of the one-dimensional array res 2,

Where res [0] indicates the maximum value of the current node does not contain a value, res [1] indicates the maximum current values ​​comprising,

So while traversing a node, the first of its recursive function calls about child node, respectively, to obtain the maximum value and does not contain child nodes contain values ​​of the left, and is not included included in the maximum value of the right child,

The current node res [0] is the larger value of the left child node in both cases plus the greater of the two cases the right child node, res [1] is the left child node does not contain the maximum value plus does not contain the maximum value of the right child node, the sum of the current node and return to see the code as follows:

c++

class Solution {
public:
    int rob(TreeNode* root) {
        vector<int> res = dfs(root);
        return max(res[0], res[1]);
    }
    vector<int> dfs(TreeNode *root) {
        if (!root) return vector<int>(2, 0);
        
        vector<int> left = dfs(root->left);
        vector<int> right = dfs(root->right);
        
        vector<int> res(2, 0);
        
        res[0] = max(left[0], left[1]) + max(right[0], right[1]);
        res[1] = left[0] + right[0] + root->val;
        
        return res;
    }
};

java

class Solution {
    public int rob(TreeNode root) {
        int[] res = dfs(root);
        return Math.max(res[0], res[1]);
    }

    public int[] dfs(TreeNode root) {
        if (root == null) return new int[2];
        int[] res = new int[2];

        int[] left = dfs(root.left);
        int[] right = dfs(root.right);

        res[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
        res[1] = left[0] + right[0] + root.val;

        return res;
    }
}

Improved Dynamic Programming

Here helper function returns the current node is the root of the maximum number rob money inside the two parameters r and l denote left child node and the right child node starts rob, respectively, the maximum number of money that can be obtained.

A recursive function which, if the current node does not exist, directly back to 0. Otherwise, the left and right child node, respectively, the function is called, to give l and r.

Also get four variables, ll and lr represents the maximum rob the left and right child nodes left child node of money, rl and rr indicate the maximum number of rob money right child nodes.

Then the value returned is actually the last two parts of the comparison value, the value of which is part of the current node value plus ll, lr, rl, and rr four values, it is not difficult to understand, because the rush of the current house, the left and right child nodes no longer grab, but four sub-node is the next layer can grab;

Another part of this housing is not grab, which grab but about two child nodes, i.e., the value of l + r, the return value to the larger value of the two parts, see the following code:

c++

class Solution {
public:
    int rob(TreeNode* root) {
        int l = 0, r = 0;
        return helper(root, l, r);
    }
    int helper(TreeNode* node, int& l, int& r) {
        if (!node) return 0;
        int ll = 0, lr = 0, rl = 0, rr = 0;
        l = helper(node->left, ll, lr);
        r = helper(node->right, rl, rr);
        return max(node->val + ll + lr + rl + rr, l + r);
    }
};

Guess you like

Origin www.cnblogs.com/wwj99/p/12408518.html