Leetcode Link: 968. 监控二叉树 - 力扣(LeetCode)
题目
给定一个二叉树,我们在树的节点上安装摄像头。
节点上的每个摄影头都可以监视其父对象、自身及其直接子对象。
计算监控树的所有节点所需的最小摄像头数量。

解法一
思路: 画图很好解决,并且通过画图,尝试,可以得知最好的方法就是从叶子节点开始往上放置。显然,应该是后序遍历。
对于一个节点,我们设置三个返回值表示三种不同的状态(有且只有这三种状态)
1 : 该点被监控了(挨着摄像机)
0 :该点放置了摄像机
-1 :该点没有被监控
采用贪心的方案,如果叶子节点有任意一个没有被监控 (-1),则都需要在该点放置一个摄像头
所有的情况如下:
- 如果叶子节点有任意一个没有被监控 (
-1),则都需要在该点放置一个摄像头 - 如果两个叶子节点都是被监控的
1,那么该点就应该是未被监控的状态(-1) - 如果两个叶子节点中一个是
0一个是1,或者两个全是0,则表示该点处于监控之中 (1)
然而,还有如下两个问题需要注意:
a. 本题中如果该节点没有被监控,我们是通过在父节点放置摄像头的。但是如果头节点没有被监控,它是没有父节点的,所以只会返回一个状态,但是不能走到放置监控并 res++ 的那一步了,所以需要我们自己补充上
b. 叶子节点一定是返回 -1 的;对于空节点,应该返回的是 1。返回 0 会导致莫名出现一个覆盖区域,返回 -1 会导致浪费摄像头
因此我们可以把空节点设置为我们的base case
题解:
class Solution:
def minCameraCover(self, root: TreeNode) -> int:
def recur(node):
nonlocal res
# base case,空节点返回1
# 同样能够保证叶子节点返回 -1
if not node:
return 1
left = recur(node.left)
right = recur(node.right)
# 两边有一边没有被监控,则放置个摄像头
if left == -1 or right == -1:
res += 1
return 0
# 两边都在覆盖范围里,则不用放置摄像头,在这个节点的父节点放一个就行
elif left == 1 and right == 1:
return -1
# 两边有一边放置了摄像头,该点就算是被监控了
# 注意判断顺序,在这里判断会简单一些,一些情况被合并了
elif left == 0 or right == 0:
return 1
res = 0
# 一定要考虑头节点,如果头节点是-1,他是没有父节点放置摄像机的,所以必需在该点放置
if recur(root) == -1:
res += 1
return res启发和联系
这个问题开始干瞪眼不会做,但是一画图就会了。
最好还是画图