Given a binary tree, we install cameras on the nodes of the tree.
Each camera at a node can monitor its parent, itself, and its immediate children.
Calculate the minimum number of cameras needed to monitor all nodes of the tree.
Example 1:
Input: [0,0,null,0,0]
Output: 1
Explanation: One camera is enough to monitor all nodes if placed as shown.
Example 2:
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.
Note:
- The number of nodes in the given tree will be in the range
[1, 1000]
. - Every node has value 0.
思路:考虑为了计算root节点的值,需要每个子节点收集什么信息,满足什么条件,可以有哪些状态。
首先,子节点的子节点必须是合理,而子节点可以是被cover到的,也可以没有cover到(当前root节点可以cover子节点)。所以子节点有2个因素会影响父节点的计算:
1. 当前子节点有没有被cover(没有被cover的话,父节点就一定要cover当前子节点)
2. 当前子节点有没有放camera(放了的话父节点就被cover了)
所以,为了计算父节点的值,需要收集子节点3(有1种状态不可能出现)种状态的值:
1. 子节点没被cover(子节点一定没有camera)
2. 子节点被cover,而且子节点处没放camera
3. 子节点被cover,而且子节点处放了camera
# Definition for a binary tree node.
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
def minCameraCover(self, root):
"""
:type root: TreeNode
:rtype: int
"""
def helper(r):
if not r: return 0,0,float('inf')
l0,l1,l2 = helper(r.left)
r0,r1,r2 = helper(r.right)
t0 = l1+r1
t1 = min(l2+min(r1,r2), r2+min(l1,l2))
t2 = 1+min(l0,l1,l2)+min(r0,r1,r2)
return t0,t1,t2
_,t1,t2 = helper(root)
return min(t1,t2)
也可以不用 “子节点没被cover” 这个状态,还是用 “有没有放camera”,这样的话就同时需要 “子节点的左子节点有没有放camera” 和 “子节点的右子节点有没有放camera”,略显麻烦。
(1)上面的思路其实是Tree之类题目的讨论,可以把类似的题目往上面的框架直接套就好了
(2)既然把计算量转移到了子节点,就不要和前面的父节点藕断丝连,比赛写的代码就是犯了这样一个错误,还把父节点的状态作为调用子节点的入参。
也可以用greedy的算法,https://leetcode.com/problems/binary-tree-cameras/discuss/211180/JavaC%2B%2BPython-Greedy-DFS
res = 0
def minCameraCover(self, root):
def dfs(root):
if not root: return 2
if not root.left and not root.right: return 0
l, r = dfs(root.left), dfs(root.right)
if l == 0 or r == 0:
self.res += 1
return 1
if l == 1 or r == 1:
return 2
return 0
return (dfs(root) == 0) + self.res
实现起来比较tricky,还不如用前一种方法直接递归暴搜。