tree
dp
dfs
]
Leetcode 0968. Binary Tree Cameras
Problem statement
https://leetcode.com/problems/binary-tree-cameras/
Solution
In by opition, this is really nice problem on the edge of two topics: binary trees and dynamic programming. We need to traverse our tree in some way and keep some information in nodes. We can say that we use here postorder traversal: to get the answer for some node
, we first collect answers for its children and then construct answer for node
. We will keep 3
pieces of information in each node:
q1
: minimum number of cameras for subtree if we put camera on this nodeq2
: minimum number of cameras for subtree if we do not put camera on this nodeq3
: minimum number of cameras for subtree, not including node itself, that isnode
is not covered
First of all, the border cases: if we reached None
node, q1
will be infinite, because we need to put camera on not-existing node, q2
and q3
are equal to 0
.
Then we calculate values for the left subtree: q1_l, q2_l, q3_l
and for the right subtree q1_r, q2_r, q3_r
.
- How we can evaluate
q1
now? By definition it is number of cameras for subtree if we put camera on this node. We also need to coverleft
andright
subtrees fully. For left subtree we can chooseq1_l
orq2_l
orq3_l
options, but in factq2_l
is always bigger or equal thenq3_l
, so we can choose only among two options. The same logic is for the right subtree. Note, that it was important here to haveq3-s
values, because we do not really need to cover left and right children, then already covered bynode
(but also we can not say we need to useq3
always, there are greedy algorithms that works, but not like this) - How we can evaluate
q2
now? By definition we are not allowed to put camera onNode
, so we need to fully cover left and right subtree. We can not use anyq3_l
orq3_r
, because we will have gap in this case. We can use any fromq1_l, q2_l
for the left subtree and any fromq1_r, q2_r
for the right subtree, so we will choose minimum from4
combinations However we need to remove caseq2_l + q2_r
, because in this casenode
will not be covered. - Howe we can evaluate
q3
now? As I mentionend,q3
ia always not smaller thanq2
, so one of the options is to just takeq2
. Or we can takeq2_l + q2_r
. Why? By definition we do not need to covernode
. So for the left and right nodes we just need to cover all subtrees, but also we do not need to covernode
itself, soq2_l
andq2_r
are enough. Note, that we can not useq1_l
orq1_r
here, because we will break the condition of not cover node
Complexity
Time complexity is O(n)
for traverse all the tree, space complexity is O(h)
, where h
is the height of the tree.
Code
class Solution:
def minCameraCover(self, root):
def dfs(node):
if not node: return (float("inf"), 0, 0)
q1_l, q2_l, q3_l = dfs(node.left)
q1_r, q2_r, q3_r = dfs(node.right)
q1 = min(q1_l, q3_l) + min(q1_r, q3_r) + 1
q2 = min(q1_l + q1_r, q1_l + q2_r, q2_l + q1_r)
q3 = min(q2, q2_l + q2_r)
return (q1, q2, q3)
return min(dfs(root)[:2])