专栏首页前端小书童一天一大 lee(打家劫舍 III)难度:中等-Day20200805

一天一大 lee(打家劫舍 III)难度:中等-Day20200805

题目:

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

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

示例

  1. 示例 1
输入: [3,2,3,null,3,null,1]

     3
    / \
   2   3
    \   \
     3   1

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

     3
    / \
   4   5
  / \   \
 1   3   1

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

抛砖引玉

抛砖引玉

思路

  • 已知相连的节点不能累加,则任意选一个节点就能将树分成两组,包含这个节点的不包含这个节点
  • 用 dpRoot 保存包含这个节点的结果
  • dp 存贮不包含这个节点的结果

设节点 node:

  • 包含 node,dpRoot[node]应该等于这个节点的值+相邻节点不被包含着的值 dpRoot[node] = node.val+dp[node.left]+dp[node.right]
  • 不包含 node,则 node.left 与 node.right 不受限,可以任选包含或者不被包含,取可能的最大值:
    • dpRootLeft[node.left]、dp[node.left]
    • dpRootLeft[node.right]、dp[node.right]

特殊条件及递归终止条件

  • root 伪 null 返回 0
  • 递归至最后一层节点 null,终止递归
/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var rob = function (root) {
  if (root === null) return 0
  // 二叉树中节点值可能重复,则使用map记录节点位置
  let dpRoot = new Map(), // 包含key对应的节点
    dp = new Map() // 不包含key对应的节点

  function dfs(node) {
    // 递归终止
    if (node === null) return 0

    // 递归枚举包含node.left的情况
    dfs(node.left)
    // 递归枚举包含node.right的情况
    dfs(node.right)

    let dpRootLeft = dpRoot.get(node.left) || 0,
      dpRootRight = dpRoot.get(node.right) || 0,
      dpLeft = dp.get(node.left) || 0,
      dpRight = dp.get(node.right) || 0

    // 包含传入节点这
    dpRoot.set(node, node.val + dpLeft + dpRight)
    // 选不包含传入节点
    dp.set(node, Math.max(dpRootLeft, dpLeft) + Math.max(dpRootRight, dpRight))
  }

  // 递归枚举包含根据点的情况
  dfs(root)

  return Math.max(dpRoot.get(root), dp.get(root))
}
  • 因为 dpRoot 与 dp 计算时都值依赖那相邻节点的值
  • 则可以再递归中返回需要相邻的包含、不包含的两种可能
/**
 * @param {TreeNode} root
 * @return {number}
 */
var rob = function (root) {
  let [dpRoot, dp] = dfs(root)

  function dfs(root) {
    if (root === null) return [0, 0]

    // 枚举分别包含左右节点的情况
    let [dpRootLeft, dpLeft] = dfs(root.left),
      [dpRootRight, dpRight] = dfs(root.right)

    let dpRoot = root.val + dpLeft + dpRight,
      dp = Math.max(dpRootLeft, dpLeft) + Math.max(dpRootRight, dpRight)

    return [dpRoot, dp]
  }

  return Math.max(dpRoot, dp)
}
  • 不相邻节点累加,即node.val与node.left、node.right不同组
  • 递归调用rob,返回包含输入节点、不包含输入点的和最大值
/**
 * @param {TreeNode} root
 * @return {number}
 */
var rob = function (root) {
  // 递归终止条件
  if (root == null) return 0

  let Root = 0,// 包含根节点
    noRoot = 0 // 不包含根节点

  // 累加存在的不相邻节点
  let Root = root.val
  if (root.left) {
    Root += rob(root.left.left) + rob(root.left.right)
  }
  if (root.right) {
    Root += rob(root.right.left) + rob(root.right.right)
  }
  // 不包含根节点节点累加
  let noRoot = rob(root.left) + rob(root.right)

  return Math.max(Root, noRoot)
}

本文分享自微信公众号 - 前端小书童(gaowenju_web),作者:坑人的小书童

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-08-05

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 一天一大 leet(二叉树展开为链表)难度:中等-Day20200802

    前端小书童
  • 一天一大 lee(恢复二叉搜索树)难度:困难-Day20200808

    前端小书童
  • 一天一大 lee(平衡二叉树)难度:简单-Day20200817

    题目:: https://leetcode-cn.com/problems/balanced-binary-tree/

    前端小书童
  • 一天一大 leet(二叉树展开为链表)难度:中等-Day20200802

    前端小书童
  • 一天一大 lee(恢复二叉搜索树)难度:困难-Day20200808

    前端小书童
  • 二叉搜索树的最近公共祖先

    百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节...

    木子星兮
  • LeetCode 1469. 寻找所有的独生节点

    二叉树中,如果一个节点是其父节点的唯一子节点,则称这样的节点为 “独生节点” 。 二叉树的根节点不会是独生节点,因为它没有父节点。

    Michael阿明
  • 最短路问题与标号算法(label correcting algorithm)研究(4)

    这是全文第三章label correcting algorithm的第二节。本章围绕Label Correcting Algorithms展开。上一节已经介绍了...

    用户1621951
  • 124. Binary Tree Maximum Path Sum

    Given a non-empty binary tree, find the maximum path sum.

    Dylan Liu
  • ZooKeeper学习第五期--ZooKeeper管理分布式环境中的数据

    本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它涉及到了paxos算法、Zab协议、通信协议等相关知 识,理解起来比较抽象...

    用户5640963

扫码关注云+社区

领取腾讯云代金券