LeetCode 968. Binary Tree Cameras
2020-05-22 20:40:11 # leetcode

Problem

LeetCode 968. Binary Tree Cameras

1. 题目简述

给出一棵二叉树,我们向节点中加入camera,每个节点可以监控其父节点和左右孩子,求最少需要多少个camera才能监控整棵树(节点不大于1000个,每个节点的value都是0)。例如:

最少camera数
Input: [0,0,null,0,null,0,null,null,0]
Output: 2
Explanation: At least two cameras are needed to monitor all nodes of the tree. The above image shows one of the valid configurations of camera placement.

2. 算法思路

Greedy:

这道题完全没思路,直接看了solution,DP解法没看懂,直接看的Greedy,逻辑思路如下。

对于任何一个节点,它都有两种状态,有camera和没camera,其中没camera又分为两种,一种是它已经被covered了,另一种是还没有。所以一共是有三种状态。我们假设某节点和其左右孩子都需要被cover,那么我们首选肯定是在父节点放入camera,这样它才能辐射范围更广,而不是需要两个孩子放camera,camera更多。所以我们的核心策略就是尽可能把camera设置到上层,而不是叶子节点。

首先我们的定义一个节点的三种状态:

  1. 有camera – 2
  2. 无camera但是被cover了 – 1
  3. 无camera并且需要父亲节点carry – 0

对于null节点,我们不需要考虑,所以其状态为1。

所以逻辑如下:

  1. 如果当前节点的左右孩子有一个为2(有camera),则当前节点为1;
  2. 如果当前节点的左右孩子有一个为0(无camera,需要父亲带飞),则当前节点为2;
  3. 如果当前节点的左右孩子都为1(都不用父亲carry),则当前节点期待父节点carry,当前节点为0;
  4. 如果根节点为0(没被孩子带飞),则result+1。

时间复杂度为O(n),空间复杂度O(h)。h为树的高度。

3. 解法

  1. Greedy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
int res = 0;
public int minCameraCover(TreeNode root) {
return getCameraState(root) == 0 ? res + 1: res;
}

private int getCameraState(TreeNode node) {
if (node == null) {
return 1;
}

int leftState = getCameraState(node.left);
int rightState = getCameraState(node.right);
if (leftState == 1 && rightState == 1) {
return 0; // 当前节点不放camera,期待被父亲carry
} else if (leftState == 0 || rightState == 0) {
res++;
return 2; // 当前节点的孩子节点存在0状态,所以需要放一个camera
} else { // 当前节点的孩子至少有一个2
return 1;
}
}
}