1、题目:监控二叉树
给定一个二叉树,我们在树的节点上安装摄像头。
节点上的每个摄影头都可以监视其父对象、自身及其直接子对象。
计算监控树的所有节点所需的最小摄像头数量。

2、解题思路
先给叶子节点父节点放个摄像头,然后隔两个节点放一个摄像头,直至到二叉树头结点。
如何考虑所有情况是很困难的,首先定义三种状态,0:该节点无覆盖,1:本节点有摄像头,2:本节点有覆盖。有二叉树,很大概率就是用递归
1、确定递归函数的参数和返回类型,返回值就是节点的状态,参数就是当前节点是哪个
2、确定终止条件,遇到了空节点,此时应该返回2(有覆盖)
3、确定单层递归的逻辑
- 情况1:左右节点都有覆盖
左孩子有覆盖,右孩子有覆盖,那么此时中间节点应该就是无覆盖的状态了。
// 左右节点都有覆盖
if (left == 2 && right == 2) return 0;
- 情况2:左右节点至少有一个无覆盖的情况
如果是以下情况,则中间节点(父节点)应该放摄像头:
left == 0 && right == 0 左右节点无覆盖 left == 1 && right == 0 左节点有摄像头,右节点无覆盖 left == 0 && right == 1 左节点有无覆盖,右节点摄像头 left == 0 && right == 2 左节点无覆盖,右节点覆盖 left == 2 && right == 0 左节点覆盖,右节点无覆盖。这个不难理解,毕竟有一个孩子没有覆盖,父节点就应该放摄像头。此时摄像头的数量要加一,并且return 1,代表中间节点放摄像头。
if (left == 0 || right == 0) {
result++;
return 1;
}
- 情况3:左右节点至少有一个有摄像头
如果是以下情况,其实就是 左右孩子节点有一个有摄像头了,那么其父节点就应该是2(覆盖的状态)
left == 1 && right == 2 左节点有摄像头,右节点有覆盖 left == 2 && right == 1 左节点有覆盖,右节点有摄像头 left == 1 && right == 1 左右节点都有摄像头
if (left == 1 || right == 1) return 2;
- 情况4:头结点没有覆盖
以上都处理完了,递归结束之后,可能头结点 还有一个无覆盖的情况
int minCameraCover(TreeNode* root) {
result = 0;
if (traversal(root) == 0) { // root 无覆盖
result++;
}
return result;
}
具体图示见下
3、代码
class Solution {
private:
int result;
int traversal(TreeNode* cur) {
// 空节点,该节点有覆盖
if (cur == NULL) return 2;
int left = traversal(cur->left); // 左
int right = traversal(cur->right); // 右
// 情况1
// 左右节点都有覆盖
if (left == 2 && right == 2) return 0;
// 情况2
// left == 0 && right == 0 左右节点无覆盖
// left == 1 && right == 0 左节点有摄像头,右节点无覆盖
// left == 0 && right == 1 左节点有无覆盖,右节点摄像头
// left == 0 && right == 2 左节点无覆盖,右节点覆盖
// left == 2 && right == 0 左节点覆盖,右节点无覆盖
if (left == 0 || right == 0) {
result++;
return 1;
}
// 情况3
// left == 1 && right == 2 左节点有摄像头,右节点有覆盖
// left == 2 && right == 1 左节点有覆盖,右节点有摄像头
// left == 1 && right == 1 左右节点都有摄像头
// 其他情况前段代码均已覆盖
if (left == 1 || right == 1) return 2;
// 以上代码我没有使用else,主要是为了把各个分支条件展现出来,这样代码有助于读者理解
// 这个 return -1 逻辑不会走到这里。
return -1;
}
public:
int minCameraCover(TreeNode* root) {
result = 0;
// 情况4
if (traversal(root) == 0) { // root 无覆盖
result++;
}
return result;
}
};
本文介绍了一种解决二叉树监控覆盖的算法,通过在叶子节点和每隔一个节点放置摄像头,最小化所需摄像头数量。首先从叶子节点开始,如果左右子节点都有覆盖,则父节点不需要摄像头;若至少一个子节点无覆盖,则父节点需放置摄像头;若左右子节点至少一个有摄像头,父节点也被覆盖。最后,若根节点无覆盖,需额外添加一个摄像头。这种方法确保了整个二叉树的覆盖。
2323

被折叠的 条评论
为什么被折叠?



