You are given the root
of a binary tree. We install cameras on the tree nodes where each camera at a node can monitor its parent, itself, and its immediate children.
Return the minimum number of cameras needed to monitor all nodes of the tree.
Example 1:
Input: root = [0,0,null,0,0] Output: 1 Explanation: One camera is enough to monitor all nodes if placed as shown.
Example 2:
Input: root = [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.
Constraints:
[1, 1000]
.Node.val == 0
This problem asks for the minimum number of cameras needed to monitor all nodes in a binary tree. A camera at a node monitors its parent, itself, and its children. The optimal solution uses dynamic programming (specifically, tree dynamic programming).
The core idea is to recursively explore the tree and determine the optimal camera placement for each subtree. For each node, we consider three possible states:
a
(Has Camera): The node has a camera installed.b
(Monitored, No Camera): The node doesn't have a camera, but it's monitored by a camera in one of its children or parent.c
(Not Monitored): The node doesn't have a camera and isn't monitored.We define a recursive function dfs(node)
that returns a triple [a, b, c]
representing the minimum number of cameras needed for each of the three states in the subtree rooted at node
. The base case is when node
is null
, returning a triple indicating an impossible state for a
(a very large number) and possible states for b
and c
(0).
The recursive step calculates the minimum cameras needed for each state:
a
(Has Camera): If a camera is placed at the current node, its children must be at least in the "monitored" state (b
). Therefore, the minimum cameras needed is 1
(for the camera at this node) plus the minimum of [la, lb, lc]
(from the left subtree) and [ra, rb, rc]
(from the right subtree).
b
(Monitored, No Camera): If the current node is monitored but doesn't have a camera, at least one of its children must have a camera, or one of its children must be in a monitored state by a child further down. We consider all possibilities.
c
(Not Monitored): If the current node is not monitored, then both its children must be in a "monitored" state (b
) to ensure complete coverage.
The final result is the minimum of a
and b
for the root node, as the root can either have a camera or be covered by its children.
Time Complexity: O(N), where N is the number of nodes in the tree. Each node is visited once during the depth-first search.
Space Complexity: O(N) in the worst case, due to the recursive call stack (depth of the tree) and the space used to store the dfs
return values. In the best case, space complexity is O(log N) for balanced trees.
class Solution:
def minCameraCover(self, root: Optional[TreeNode]) -> int:
inf = float('inf')
def dfs(node):
if not node:
return inf, 0, 0 # Impossible, Monitored, Not Monitored
la, lb, lc = dfs(node.left)
ra, rb, rc = dfs(node.right)
a = 1 + min(la, lb, lc) + min(ra, rb, rc) # Camera at current node
b = min(la + rb, lb + ra, la + ra) # Monitored, no camera
c = lb + rb # Not monitored
return a, b, c
a, b, _ = dfs(root)
return min(a, b)
The implementations in other languages (Java, C++, Go, TypeScript) follow the same logic, adapting syntax and data structures to their respective languages. The core algorithm remains consistent across all of them.