题目地址:
https://leetcode.com/problems/binary-tree-cameras/
给定一棵二叉树,允许在每个节点上放置“守卫”,其可以守卫当前节点以及与其相邻的节点(父亲节点和两个孩子都会被守卫到)。问最少放多少个守卫就可以使得所有节点都被守卫到。
思路是动态规划。设
f
[
x
]
f[x]
f[x]表示当
x
x
x子树都被守卫到的情况下的最小守卫数量,
f
[
x
]
f[x]
f[x]是个长
3
3
3的数组,
f
[
x
]
[
0
]
f[x][0]
f[x][0]表示
x
x
x处没有守卫并且其被其父亲的守卫所守卫的情况,
f
[
x
]
[
1
]
f[x][1]
f[x][1]表示
x
x
x处没有守卫并且其被其某个孩子的守卫所守卫的情况,
f
[
x
]
[
2
]
f[x][2]
f[x][2]表示
x
x
x处有守卫的情况。设
l
l
l和
r
r
r分别是
x
x
x的左右孩子,如果
x
x
x为空,则
f
[
x
]
=
[
0
,
0
,
∞
]
f[x]=[0,0,\infty]
f[x]=[0,0,∞],
∞
\infty
∞表示该情况无效;否则:
{
f
[
x
]
[
0
]
=
min
{
l
[
1
]
,
l
[
2
]
}
+
min
{
r
[
1
]
,
r
[
2
]
}
f
[
x
]
[
1
]
=
min
{
l
[
2
]
+
min
{
r
[
1
]
,
r
[
2
]
}
,
r
[
2
]
+
min
{
l
[
1
]
,
l
[
2
]
}
}
f
[
x
]
[
2
]
=
1
+
min
{
l
[
0
]
,
l
[
1
]
,
l
[
2
]
}
+
min
{
r
[
0
]
,
r
[
1
]
,
r
[
2
]
}
\begin{cases}f[x][0]=\min\{l[1],l[2]\}+\min\{r[1],r[2]\} \\f[x][1]=\min\{l[2]+\min\{r[1],r[2]\}, r[2]+\min\{l[1],l[2]\}\}\\f[x][2]=1+\min\{l[0],l[1],l[2]\} + \min\{r[0],r[1],r[2]\} \end{cases}
⎩
⎨
⎧f[x][0]=min{l[1],l[2]}+min{r[1],r[2]}f[x][1]=min{l[2]+min{r[1],r[2]},r[2]+min{l[1],l[2]}}f[x][2]=1+min{l[0],l[1],l[2]}+min{r[0],r[1],r[2]}三种情况分别是:
1、
x
x
x处没有守卫并且其被其父亲的守卫所守卫,那么两个孩子分别独立,并且每个孩子要么被它自己守卫,要么被它的孩子守卫,取最小然后算个总和即可;
2、
x
x
x处没有守卫并且其被其某个孩子的守卫所守卫,那么要么其左孩子被自己守卫,右孩子可以被自己也可以被它的孩子守卫;要么对称着,其右孩子被自己守卫,左孩子可以被自己也可以被它的孩子守卫;
3、
x
x
x处有守卫,那么左右孩子独立,并且随意搭配。
代码如下:
public class Solution {
public int minCameraCover(TreeNode root) {
int[] res = dfs(root);
return Math.min(res[1], res[2]);
}
int[] dfs(TreeNode cur) {
if (cur == null) {
return new int[]{0, 0, 0x3f3f3f3f};
}
int[] left = dfs(cur.left), right = dfs(cur.right);
int[] res = new int[3];
res[0] = Math.min(left[1], left[2]) + Math.min(right[1], right[2]);
res[1] = Math.min(left[2] + Math.min(right[1], right[2]), right[2] + Math.min(left[1], left[2]));
res[2] = 1 + Math.min(left[0], Math.min(left[1], left[2])) + Math.min(right[0], Math.min(right[1], right[2]));
return res;
}
}
class TreeNode {
int val;
TreeNode left, right;
public TreeNode(int val) {
this.val = val;
}
}
时间复杂度 O ( n ) O(n) O(n),空间 O ( h ) O(h) O(h)。
C++:
class Solution {
public:
int minCameraCover(TreeNode* root) {
auto res = dfs(root);
return min(res[1], res[2]);
}
vector<int> dfs(TreeNode* cur) {
if (!cur) return {0, 0, INT_MAX / 2};
auto l = dfs(cur->left), r = dfs(cur->right);
return {min(l[1], l[2]) + min(r[1], r[2]),
min(l[2] + min(r[1], r[2]), r[2] + min(l[1], l[2])),
1 + min(l[0], min(l[1], l[2])) + min(r[0], min(r[1], r[2]))};
}
};
时空复杂度一样。