Binary Tree Cameras

HardTree DP · Greedy Post-Order🧩 Tree & Graph DPLeetCode #968 ↗Updated

Problem

Cameras can be installed on nodes of a binary tree; a camera watches its own node, its parent and its direct children. Given the root, return the fewest cameras needed so that every node is watched.
Input[0,0,null,0,0]Output1
Input[0,0,null,0,null,0,null,null,0]Output2

1 ≤ n ≤ 1000  ·  Node.val == 0

Try it yourself

Java
class Solution {
    public int minCameraCover(TreeNode root) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
Never put a camera on a leaf: its parent covers the leaf plus more. Work bottom-up, and place a camera only when a child would otherwise stay unwatched — three states per node are enough.
PatternTree & Graph DP

Instinct A node's best answer depends only on its children's answers - post-order DFS that returns a tiny tuple of states per node.

Memory hack Kids report up, parent decides - every subtree hands its parent a small report card, and the parent never re-reads the kids' homework.

Open the Tree & Graph DP guide →

Approaches

Brute ForceTry Every Camera Subset

Time O(2n·n)Space O(n)

Index the nodes and remember each one's parent. For every bitmask of camera positions, check in O(n) that each node has a camera on itself, its parent or a child, and keep the smallest valid popcount.

Java
private final List<Integer> parent = new ArrayList<>();

public int minCameraCover(TreeNode root) {
    collect(root, -1);
    int n = parent.size(), best = n;
    for (int mask = 0; mask < (1 << n); mask++)
        if (Integer.bitCount(mask) < best && allWatched(mask)) best = Integer.bitCount(mask);
    return best;
}
private void collect(TreeNode node, int par) { // pre-order ids, record parents
    if (node == null) return;
    int id = parent.size();
    parent.add(par);
    collect(node.left, id);
    collect(node.right, id);
}
private boolean allWatched(int mask) {
    boolean[] ok = new boolean[parent.size()];
    for (int i = 0; i < ok.length; i++) {
        int p = parent.get(i);
        boolean camI = (mask >> i & 1) == 1, camP = p >= 0 && (mask >> p & 1) == 1;
        if (camI || camP) ok[i] = true;   // own or parent's camera
        if (camI && p >= 0) ok[p] = true; // a child's camera watches its parent
    }
    for (boolean b : ok) if (!b) return false;
    return true;
}

A useful oracle for tiny trees; hopeless beyond ~20 nodes.

At a glance

LevelApproachTimeSpace
Brute ForceTry Every Camera SubsetO(2n·n)O(n)
BetterTree DP with 3 StatesO(n)O(h)
OptimalGreedy Post-Order (Leaves Up)O(n)O(h)
Common pitfalls
  • Treating null as “needs cover” — leaves get cameras.
  • Skipping the final root check — an uncovered root needs a camera.
  • Testing “child has camera” before “child needs cover”.
Interview tips
  • Justify greedy by exchange: moving a leaf camera up never hurts.
  • Name the three states explicitly before coding.
  • Offer the DP version if cameras get different costs.
Pattern
Post-order tree DP / greedy with node states → covering or dominating-set problems on trees.
My notes saved in this browser