[路飞] leetcode 968. 监控二叉树

145 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第 1 天,点击查看活动详情

一、题目描述

leetcode 968. 监控二叉树

给定一个二叉树,我们在树的节点上安装摄像头。

节点上的每个摄影头都可以监视其父对象、自身及其直接子对象。

计算监控树的所有节点所需的最小摄像头数量。

示例 1:

image.png

输入: [0,0,null,0,0]
输出: 1
解释: 如图所示,一台摄像头足以监控所有节点。

示例 2:

输入:[0,0,null,0,null,0,null,null,0]
输出:2
解释:需要至少两个摄像头来监视树的所有节点。 上图显示了摄像头放置的有效位置之一。

提示:

  1. 给定树的节点数的范围是 [1, 1000]
  2. 每个节点的值都是 0。

二、思路分析

定义递归函数:返回当前节点所在子树,需要的最少摄像头数量。

定义一个二维数组 dp[父节点是否安置摄像头][当前节点是否安置摄像头],0表示未安置,1表示安置摄像头。

例如 :

  • dp[0][0]表示当前父节点不安置摄像头,当前节点也不安置摄像头。(那么当前的左子节点或右子节点需要有一个放置摄像头,或者都放置摄像头)

  • dp[0][1]表示当前父节点不安置摄像头,当前节点安置摄像头。(当前的左子节点或右子节点可以放置摄像头,也可以不放置;可以都放置也可以都不放置)

  • dp[1][0]表示当前父节点安置摄像头,当前节点不安置摄像头。(当前的左子节点或右子节点可以放置摄像头,也可以不放置;可以都放置也可以都不放置)

  • dp[1][1]表示当前父节点安置摄像头,当前节点不安置摄像头。(当前的左子节点或右子节点可以放置摄像头,也可以不放置;可以都放置也可以都不放置)

  • 边界处理

    1. 如果是空节点,不能放置摄像头

      dp[0][0] = 0; // 当前数量为0
      dp[0][1] = 10000; // 不符合要求,随意设置成了超出题目最大限制的数
      dp[1][0] = 0;
      dp[1][1] = 10000;
      
    2. 如果当前是叶子节点

      dp[0][0] = 10000; // 父节点没有放置,当前节点也没放置,不符合要求
      dp[0][1] = 1; // 父节点没有放置,当前节点放置了,当前节点所在子树放置数量为1
      dp[1][0] = 0; // 父节点放置了,当前节点没有放置,当前节点所在子树放置数量为0
      dp[1][1] = 1; // 父节点放置了,当前节点也放置了,当前节点所在子树放置数量为1
      
    3. 上面边界处理完后,递归处理节点左子树和节点右子树。

最终结果取dp[0][1],dp[0][0]中最小值;也就是父节点不放置时,在当前节点安置与当前节点不安置时那个数量最小。

三、JavaScript代码

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
function getDp(root, dp) {
    if(root == null) {
        dp[0][0] = 0;
        dp[0][1] = 10000;
        dp[1][0] = 0;
        dp[1][1] = 10000;
        return;
    }
    if(root.left == null && root.right == null) {
        dp[0][0] = 10000;
        dp[0][1] = 1;
        dp[1][0] = 0;
        dp[1][1] = 1;
        return;
    }
    let l = [new Array(2), new Array(2)], r = [new Array(2), new Array(2)];
    getDp(root.left, l);
    getDp(root.right, r)
    dp[0][0] = Math.min(Math.min(l[0][1]+r[0][0], l[0][0]+r[0][1]) ,l[0][1]+r[0][1]);
    dp[1][0] = Math.min(dp[0][0], l[0][0]+r[0][0]);
    dp[0][1] = Math.min(Math.min(l[1][1]+r[1][0], l[1][0]+r[1][1]), Math.min(l[1][1]+r[1][1], l[1][0]+r[1][0])) +1;
    dp[1][1] = dp[0][1]
}
var minCameraCover = function(root) {
    let dp = [new Array(2), new Array(2)]
    getDp(root, dp);
    return Math.min(dp[0][1],dp[0][0])
};

四、总结