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.
For example:
Input: root = [0,0,null,0,0] Output: 1 Explanation: One camera is enough to monitor all nodes if placed as shown.
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:
The number of nodes in the tree is in the range [1, 1000]
.
Node.val == 0
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
def minCameraCover(self, root: TreeNode) -> int:
# 0: Not covered, need a camera at parent
# 1: Covered, but no camera here
# 2: Has a camera
self.camera_count = 0
def dfs(node):
if not node: # Null node is considered covered
return 1
left_state = dfs(node.left)
right_state = dfs(node.right)
if left_state == 0 or right_state == 0:
# If any child needs a camera, install one here
self.camera_count += 1
return 2
if left_state == 2 or right_state == 2:
# If any child has a camera, this node is covered
return 1
# Otherwise, this node is not covered
return 0
# Handle the root node
if dfs(root) == 0:
self.camera_count += 1
return self.camera_count
The problem requires finding the minimum number of cameras to cover all nodes in a binary tree, where a camera at a node covers its parent, itself, and its immediate children.
Naive Approach (Not Implemented):
A naive approach might involve trying all possible camera placements and finding the minimum number of cameras that cover all nodes. This would be highly inefficient due to the exponential number of possible placements.
Optimal Approach:
The optimal approach uses a depth-first search (DFS) and a state-based strategy to determine the placement of cameras. Each node can be in one of three states:
The DFS function recursively traverses the tree, determining the state of each node based on the states of its children. The algorithm prioritizes covering nodes with cameras as low in the tree as possible.
None
(null), it is considered covered (state 1).camera_count
and set the current node's state to 2).Example:
Consider the tree [0,0,null,0,0]
. The algorithm would work as follows:
None
(covered, state 1).camera_count
becomes 1. The left child's state becomes 2.camera_count
, which is 1.The runtime complexity is O(N), where N is the number of nodes in the tree. The DFS function visits each node once.
The space complexity is O(H), where H is the height of the tree, due to the recursive call stack. In the worst case (skewed tree), H can be equal to N, resulting in O(N) space complexity. In the average case (balanced tree), H is log(N), resulting in O(log N) space complexity.
None
), no cameras are needed, and the function should return 0.