【LeetCode】337. House Robber III 打家劫舍 III(Medium)(JAVA)

【LeetCode】337. House Robber III 打家劫舍 III(Medium)(JAVA)

题目地址: 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:

Input: [3,2,3,null,3,null,1]

     3
    / \
   2   3
    \   \ 
     3   1

Output: 7 
Explanation: Maximum amount of money the thief can rob = 3 + 3 + 1 = 7.

Example 2:

Input: [3,4,5,1,3,null,1]

     3
    / \
   4   5
  / \   \ 
 1   3   1

Output: 9
Explanation: Maximum amount of money the thief can rob = 4 + 5 = 9.

题目大意

在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。 除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。

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

解题方法

暴力求解
  1. 直接暴力每个都判断当前是否需要偷;如果当前偷,下一个就不能再偷,如果当前不偷,下一个就可以偷
  2. 每次都需要遍历子树两次
class Solution {
    public int rob(TreeNode root) {
        return robHelp(root, true);
    }

    public int robHelp(TreeNode root, boolean canRob) {
        if (root == null) return 0;
        if (canRob) {
            return Math.max(robHelp(root.left, true) + robHelp(root.right, true), root.val + robHelp(root.left, false) + robHelp(root.right, false));
        } else {
            return robHelp(root.left, true) + robHelp(root.right, true);
        }
    }
}

执行耗时:1546 ms,击败了5.00% 的Java用户
内存消耗:38.5 MB,击败了36.54% 的Java用户

优化
  1. 暴力方法对子树每次都遍历了两遍,造成越往下,遍历的次数是指数增长的,所以想办法能不能遍历一次就把偷和不偷的结果都返回呢?
  2. 这样需要返回值是一个数组(同时返回偷和不偷的结果)
  3. 如果偷的话,子树肯定就不能偷了,就是 root.val + function(roo.left)[不偷] + …;
  4. 如果不偷,那子树既可以偷也可以不偷,取两个的最大值,Math.max(function(root.left)[偷], function(root.left)[不偷])
class Solution {
    public int rob(TreeNode root) {
        int[] res = robHelp(root);
        return Math.max(res[0], res[1]);
    }

    // int[0]: rob; int[1]: not rob
    public int[] robHelp(TreeNode root) {
        if (root == null) return new int[]{0, 0};
        int[] left = robHelp(root.left);
        int[] right = robHelp(root.right);
        return new int[]{left[1] + right[1] + root.val, Math.max(left[0], left[1]) + Math.max(right[0], right[1])};
    }
}

执行耗时:0 ms,击败了100.00% 的Java用户
内存消耗:38.3 MB,击败了58.62% 的Java用户

欢迎关注我的公众号,LeetCode 每日一题更新
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值