一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第 1 天,点击查看活动详情。
一、题目描述
给定一个二叉树,我们在树的节点上安装摄像头。
节点上的每个摄影头都可以监视其父对象、自身及其直接子对象。
计算监控树的所有节点所需的最小摄像头数量。
示例 1:
输入: [0,0,null,0,0]
输出: 1
解释: 如图所示,一台摄像头足以监控所有节点。
示例 2:
输入:[0,0,null,0,null,0,null,null,0]
输出:2
解释:需要至少两个摄像头来监视树的所有节点。 上图显示了摄像头放置的有效位置之一。
提示:
- 给定树的节点数的范围是
[1, 1000]。 - 每个节点的值都是 0。
二、思路分析
定义递归函数:返回当前节点所在子树,需要的最少摄像头数量。
定义一个二维数组 dp[父节点是否安置摄像头][当前节点是否安置摄像头],0表示未安置,1表示安置摄像头。
例如 :
-
dp[0][0]表示当前父节点不安置摄像头,当前节点也不安置摄像头。(那么当前的左子节点或右子节点需要有一个放置摄像头,或者都放置摄像头) -
dp[0][1]表示当前父节点不安置摄像头,当前节点安置摄像头。(当前的左子节点或右子节点可以放置摄像头,也可以不放置;可以都放置也可以都不放置) -
dp[1][0]表示当前父节点安置摄像头,当前节点不安置摄像头。(当前的左子节点或右子节点可以放置摄像头,也可以不放置;可以都放置也可以都不放置) -
dp[1][1]表示当前父节点安置摄像头,当前节点不安置摄像头。(当前的左子节点或右子节点可以放置摄像头,也可以不放置;可以都放置也可以都不放置) -
边界处理
-
如果是空节点,不能放置摄像头
dp[0][0] = 0; // 当前数量为0 dp[0][1] = 10000; // 不符合要求,随意设置成了超出题目最大限制的数 dp[1][0] = 0; dp[1][1] = 10000; -
如果当前是叶子节点
dp[0][0] = 10000; // 父节点没有放置,当前节点也没放置,不符合要求 dp[0][1] = 1; // 父节点没有放置,当前节点放置了,当前节点所在子树放置数量为1 dp[1][0] = 0; // 父节点放置了,当前节点没有放置,当前节点所在子树放置数量为0 dp[1][1] = 1; // 父节点放置了,当前节点也放置了,当前节点所在子树放置数量为1 -
上面边界处理完后,递归处理节点左子树和节点右子树。
-
最终结果取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])
};