leetcode hot100之打家劫舍 III(337)解析

160 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第26天,点击查看活动详情


前言

  • leetcode hot100,是大厂面试高频题,也是必刷算法题。精选了100道LeetCode上最热门的题目,适合初识算法与数据结构的新手和想要在短时间内高效提升的人,按照官方说的,熟练掌握这 100 道题,就具备了代码世界通行的基本能力。

leetcode337题(打家劫舍 III)

本文来讲hot100第337题( 打家劫舍 III),本题是树结构的动态规划题目。需要了解树的几种遍历方式,还需要对动态规划有了解。

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

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

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

示例:

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

提示:

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

分析

  • 房子排列是二叉树
  • 不可选相连的2个房子,也就是有父子关系的节点
  • 求最高金额,就是求选择的节点的和最大
  • 本题是树型的动态规划题目,需要对树的遍历方式足够了解

思路

  • 我们使用状态转移容器来记录状态的变化,
  • 这里使用一个数组,记录当前节点偷与不偷所得到的的最大金钱。
  • 首先明确的是使用后序遍历。 因为通过递归函数的返回值来做下一步计算。
  • 通过递归左节点,得到左节点偷与不偷的金钱。
  • 通过递归右节点,得到右节点偷与不偷的金钱

代码

 const postOrder = (node) => {
    // 递归出口
    if (!node) return [0, 0];
    // 遍历左子树
    const left = postOrder(node.left);
    // 遍历右子树
    const right = postOrder(node.right);
    // 不偷当前节点,左右子节点都可以偷或不偷,取最大值
    const DoNot = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
    // 偷当前节点,左右子节点只能不偷
    const Do = node.val + left[0] + right[0];
    // [不偷,偷]
    return [DoNot, Do];
  };
  const res = postOrder(root);
  // 返回最大值
  return Math.max(...res);

结语

  • 本题是树结构的动态规划题目。理解了题目,核心在于选或不选,我们需要了解树的几种遍历方式,层序遍历,前序遍历,中序遍历,后序遍历,还需要对动态规划有了解。