LeetCode 题解工作台

打家劫舍 III

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

category

4

题型

code_blocks

5

代码语言

hub

3

相关题

当前训练重点

中等 · 二分·树·traversal

bolt

答案摘要

我们定义一个函数 ,表示偷取以 为根的二叉树的最大金额。该函数返回一个二元组 $(a, b)$,其中 表示偷取 节点时能得到的最大金额,而 表示不偷取 节点时能得到的最大金额。 函数 的计算过程如下:

Interview AiBox logo

Interview AiBox 实时 AI 助手,陪你讲清 二分·树·traversal 题型思路

试试 AiBox 面试助手arrow_forward
description

题目描述

小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 root 。

除了 root 之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 两个直接相连的房子在同一天晚上被打劫 ,房屋将自动报警。

给定二叉树的 root 。返回 在不触动警报的情况下 ,小偷能够盗取的最高金额 。

 

示例 1:

输入: root = [3,2,3,null,3,null,1]
输出: 7 
解释: 小偷一晚能够盗取的最高金额 3 + 3 + 1 = 7

示例 2:

输入: root = [3,4,5,1,3,null,1]
输出: 9
解释: 小偷一晚能够盗取的最高金额 4 + 5 = 9

 

提示:

  • 树的节点数在 [1, 104] 范围内
  • 0 <= Node.val <= 104
lightbulb

解题思路

方法一:树形 DP

我们定义一个函数 dfs(root)dfs(root),表示偷取以 rootroot 为根的二叉树的最大金额。该函数返回一个二元组 (a,b)(a, b),其中 aa 表示偷取 rootroot 节点时能得到的最大金额,而 bb 表示不偷取 rootroot 节点时能得到的最大金额。

函数 dfs(root)dfs(root) 的计算过程如下:

如果 rootroot 为空,那么显然有 dfs(root)=(0,0)dfs(root) = (0, 0)

否则,我们首先计算出左右子节点的结果,即 dfs(root.left)dfs(root.left)dfs(root.right)dfs(root.right),这样就得到了两对值 (la,lb)(l_a, l_b) 以及 (ra,rb)(r_a, r_b)。对于 dfs(root)dfs(root) 的结果,我们可以分为两种情况:

  • 如果偷取 rootroot 节点,那么不能偷取其左右子节点,结果为 root.val+lb+rbroot.val + l_b + r_b
  • 如果不偷取 rootroot 节点,那么可以偷取其左右子节点,结果为 max(la,lb)+max(ra,rb)\max(l_a, l_b) + \max(r_a, r_b)

在主函数中,我们可以直接返回 dfs(root)dfs(root) 的较大值,即 max(dfs(root))\max(dfs(root))

时间复杂度 O(n)O(n),空间复杂度 O(n)O(n)。其中 nn 是二叉树的节点数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def rob(self, root: Optional[TreeNode]) -> int:
        def dfs(root: Optional[TreeNode]) -> (int, int):
            if root is None:
                return 0, 0
            la, lb = dfs(root.left)
            ra, rb = dfs(root.right)
            return root.val + lb + rb, max(la, lb) + max(ra, rb)

        return max(dfs(root))
speed

复杂度分析

指标
时间Depends on the final approach
空间Depends on the final approach
psychology

面试官常问的追问

外企场景
  • question_mark

    Look for the candidate's ability to traverse a binary tree efficiently using DFS.

  • question_mark

    Assess their understanding of dynamic programming and state tracking in tree problems.

  • question_mark

    Evaluate if they can handle large inputs effectively by applying memoization techniques.

warning

常见陷阱

外企场景
  • error

    Forgetting to account for the constraint that no two directly-linked houses can be robbed.

  • error

    Overlooking the importance of memoization in improving time complexity for larger trees.

  • error

    Failing to properly track and compare both robbed and skipped states for each node.

swap_horiz

进阶变体

外企场景
  • arrow_right_alt

    Modify the problem to work with a general graph instead of a binary tree, adding complexity in terms of adjacency.

  • arrow_right_alt

    Introduce a limit on the number of houses that can be robbed in a single night, adding an extra layer of optimization.

  • arrow_right_alt

    Change the tree to a non-binary tree, where each node can have an arbitrary number of children, altering the DFS approach.

help

常见问题

外企场景

打家劫舍 III题解:二分·树·traversal | LeetCode #337 中等