Leetcode 968. Binary Tree Cameras

Problem Explanation:

The problem is a tree problem where we are given a binary tree and our task is to position cameras at the nodes of the tree such that the entire tree can be monitored. A camera at a node can monitor its parent, itself, and its immediate children. The goal is to position the cameras such that the minimum number of cameras is used.

For example, consider the binary tree:

1
2
3   0
4  / \
5 0   0

Here, we can place a camera at the root of the tree and all the nodes will be covered. So, the minimum number of cameras needed is 1.

Solution Approach:

The solution uses Depth-first Search (DFS) and dynamic programming. The idea is to build up the solution from each subtree and propagate that information upwards.

At each node, we maintain an array of three integers. The array represents three states:

  • The minimum number of cameras needed if the current node is not covered
  • The minimum number of cameras needed if the current node is covered without a camera
  • The minimum number of cameras needed if the current node is covered with a camera here

For each child node, we recursively perform the same operation and accumulate the results.

After exploring all child nodes of a node, we can calculate the minimum number of cameras needed for the three states of the current node based on the child nodes' states.

Here is how the solution works:

For the current node:

  • If it is not covered, then at least one of its children should have a camera.
  • If it is covered without a camera, we can either place a camera at one of its children or not, since it is already covered from its parent.
  • If it is covered with a camera, we simply add one camera to the total number of cameras and cover all of its children whether they have a camera or not since the current node covers them.

Finally, we return the minimum of covered-with-camera and covered-without-camera for the root node.

Python Solution:

1
2python
3class Solution:
4    def minCameraCover(self, root):
5        def dfs(root):
6            if not root:
7                return [0, 0, float('inf')]
8            la, lb, lc = dfs(root.left)
9            ra, rb, rc = dfs(root.right)
10            a = lb + rb
11            b = min(lc + min(ra, rb), rc + min(la, lb))
12            c = min(la, lb, lc) + min(ra, rb, rc) + 1
13            return [a, b, c]
14        
15        a, b, c = dfs(root)
16        return min(b, c)

Java Solution:

1
2java
3class Solution {
4    public int minCameraCover(TreeNode root) {
5        int[] ans = dfs(root);
6        return Math.min(ans[1], ans[2]);
7    }
8
9    private int[] dfs(TreeNode root) {
10        if (root == null)
11            return new int[]{0, 0, 1000};
12
13        int[] l = dfs(root.left);
14        int[] r = dfs(root.right);
15
16        int s0 = l[1] + r[1];
17        int s1 = Math.min(l[2] + Math.min(r[1], r[2]), r[2] + Math.min(l[1], l[2]));
18        int s2 = 1 + Math.min(Math.min(l[0], l[1], l[2]), Math.min(r[0], r[1], r[2]));
19
20        return new int[]{s0, s1, s2};
21    }
22}

JavaScript Solution:

1
2javascript
3class Solution {
4    minCameraCover(root) {
5        let ans = dfs(root);
6        return Math.min(ans[1], ans[2]);
7    }
8
9    dfs(root) {
10        if (root == null)
11            return [0, 0, 1000];
12
13        let l = dfs(root.left);
14        let r = dfs(root.right);
15
16        let s0 = l[1] + r[1];
17        let s1 = Math.min(l[2] + Math.min(r[1], r[2]), r[2] + Math.min(l[1], l[2]));
18        let s2 = 1 + Math.min(Math.min(l[0], l[1], l[2]), Math.min(r[0], r[1], r[2]));
19
20        return [s0, s1, s2];
21    }
22}

C++ Solution:

1
2cpp
3class Solution {
4public:
5    int minCameraCover(TreeNode* root) {
6        vector<int> ans = dfs(root);
7        return min(ans[1], ans[2]);
8    }
9
10private:
11    vector<int> dfs(TreeNode* root) {
12        if (root == nullptr)
13            return {0, 0, 1000};
14
15        vector<int> l = dfs(root->left);
16        vector<int> r = dfs(root->right);
17
18        int s0 = l[1] + r[1];
19        int s1 = min(l[2] + min(r[1], r[2]), r[2] + min(l[1], l[2]));
20        int s2 = min({l[0], l[1], l[2]}) + min({r[0], r[1], r[2]}) + 1;
21
22        return {s0, s1, s2};
23    }
24};

C# Solution:

1
2csharp
3public class Solution {
4    public int MinCameraCover(TreeNode root) {
5        int[] ans = Dfs(root);
6        return Math.Min(ans[1], ans[2]);
7    }
8
9    private int[] Dfs(TreeNode root) {
10        if (root == null)
11            return new int[]{0, 0, 1000};
12
13        int[] l = Dfs(root.left);
14        int[] r = Dfs(root.right);
15
16        int s0 = l[1] + r[1];
17        int s1 = Math.Min(l[2] + Math.Min(r[1], r[2]), r[2] + Math.Min(l[1], l[2]));
18        int s2 = 1 + Math.Min(Math.Min(l[0], l[1], l[2]), Math.Min(r[0], r[1], r[2]));
19
20        return new int[]{s0, s1, s2};
21    }
22}

In these implementations, the dfs function iteratively checks each node in the binary tree and updates the minimum count of cameras needed according to the rules described in the approach. The final result is the minimum of covered-with-camera and covered-without-camera for the root node.In conclusion, this problem can be solved by using a combination of Depth-first Search (DFS) and dynamic programming. By considering a binary tree as a collection of smaller sub-trees and calculating the minimum number of cameras required for each case, we are able to find the optimal solution. Although the implementations may differ a bit according to the syntax and libraries of different programming languages, the basic approach remains the same. The solutions provided in this article for Python, Java, JavaScript, C++ and C# are efficient and well-optimized for the given problem and can be further improved as per the requirements of a specific application or use case.

For future enhancements, we can also consider the problem where each node in the tree has an associated cost parameter that we need to minimize during the camera placement. This cost parameter could include things like cost of camera or cost of installation, etc. The basic approach would be similar to the current solution, but may require additional steps to optimize the cost.


Got a question? Ask the Teaching Assistant anything you don't understand.

Still not clear? Ask in the Forum,  Discord or Submit the part you don't understand to our editors.


TA 👨‍🏫