方法1
DFS: divide-and-conquer, analyze current values from left and right nodes
there are three return values: camera numbers when
(1) All the nodes below this node are covered, but not this node.
(2) All the nodes below and including this node are covered, but there is no camera here.
(3) Placed camera: All the nodes below and including this node are covered, and there is a camera here (which may cover nodes above this node).
class Solution:
def minCameraCover(self, root: TreeNode) -> int:
not_covered, covered, occupied = self.dfs(root)
return min(covered, occupied)
def dfs(self, root):
if not root:
return 0, 0, float('inf')
left = self.dfs(root.left)
right = self.dfs(root.right)
not_covered = left[1] + right[1]
covered = min(left[2] + min(right[1:]), right[2] + min(left[1:]))
occupied = 1 + min(left) + min(right)
return not_covered, covered, occupied
方法2
Greedy method: Bottom-up, 默认leaf node不放camera
class Solution:
def minCameraCover(self, root: TreeNode) -> int:
self.ans = 0
self.dfs(root, None, {None}) # None in set,
return self.ans
def dfs(self, root, par, covered):
if not root:
return
self.dfs(root.left, root, covered)
self.dfs(root.right, root, covered)
if par is None and root not in covered or root.left not in covered or root.right not in covered: # leaf node不放camera
self.ans += 1
covered.update({root, par, root.left, root.right})