[leetcode] 337. House Robber III 解题报告

题目链接: https://leetcode.com/problems/house-robber-iii/

The thief has found himself a new place for his thievery again. There is only one entrance to this area, called the "root." Besides the root, each house has one and only one parent house. After a tour, the smart thief realized that "all houses in this place forms a binary tree". It will automatically contact the police if two directly-linked houses were broken into on the same night.

Determine the maximum amount of money the thief can rob tonight without alerting the police.

Example 1:

     3
    / \
   2   3
    \   \ 
     3   1
Maximum amount of money the thief can rob =  3  +  3  +  1  =  7 .

Example 2:

     3
    / \
   4   5
  / \   \ 
 1   3   1
Maximum amount of money the thief can rob =  4  +  5  =  9 .


思路: 一个基本的思路就是每一个结点做两种判断, 偷或者不偷, 所以在做DFS搜索的时候我们可以在每一个结点判断哪一个情况利益更大. 我们需要一个标记, 就是如果上一个结点被偷了, 这个结点就不可以再偷了, 所以一个基本的代码如下, 但是无法通过所有数据:

class Solution {
public:
    int DFS(TreeNode* root, bool flag)
    {
        if(!root) return 0;
        int sum = DFS(root->left, true) + DFS(root->right, true);//不偷这个,则其子节点可以偷
        if(flag == true)//如果当前结点可以偷, 那么下一个结点则不可以
            sum = max(DFS(root->left, false)+ DFS(root->right, false)+root->val, sum);
        return sum;
    }

    int rob(TreeNode* root) {
        return max(DFS(root, false), DFS(root, true));
    }
};

我们可以看到这种方法包含了很多重复的计算, 那么我们可以将计算过的结点保存起来, 如果下次再遍历到这里的时候可以直接得到其值, 改进的方法如下:

class Solution {
public:
    int DFS(TreeNode* root, bool flag)
    {
        if(!root) return 0;
        int sum1, sum2;
        if(hash1.find(root) != hash1.end())
            sum1 = hash1[root];
        else
        {
            sum1 = DFS(root->left, true) + DFS(root->right, true);
            hash1[root] = sum1;
        }
        if(flag && hash2.find(root)!= hash2.end())
            sum2 = hash2[root];
        else if(flag)
        {
            sum2 = DFS(root->left, false)+ DFS(root->right, false)+root->val;
            hash2[root] = sum2;
        }
        return max(sum1, sum2);
    }

    int rob(TreeNode* root) {
        return max(DFS(root, false), DFS(root, true));
    }
private:
    unordered_map<TreeNode*, int> hash1;
    unordered_map<TreeNode*, int> hash2;
};

这种方法已经足以通过所有数据, 并且也相当高效, 不过代码比较复杂, 参考别人的代码发现一种更好的方式, 并且不需要特殊的数据结构, 因此效率比我的代码更高.

代码如下:

class Solution {
public:
    int DFS(TreeNode* root, int& sonLeft, int& sonRight)
    {
        if(!root) return 0;
        int leftSonLeft=0, leftSonRight=0, rightSonLeft=0, rightSonRight=0;
        sonLeft = DFS(root->left, leftSonLeft, leftSonRight);
        sonRight = DFS(root->right, rightSonLeft, rightSonRight);
        int fromGrandson = leftSonLeft+leftSonRight+ rightSonLeft+ rightSonRight;
        return max(root->val + fromGrandson, sonLeft + sonRight);
    }

    int rob(TreeNode* root) {
        int sonLeft=0, sonRight=0;
        return DFS(root, sonLeft, sonRight);
    }
};
参考链接:https://leetcode.com/discuss/93998/simple-c-solution

你可能感兴趣的:(LeetCode,DFS)