跳至主要內容

968, 监控二叉树

Mike大约 4 分钟greedyhardbinary treedepth first searchdynamic programming

一、题目描述

给定一个二叉树,我们在树的节点上安装摄像头。

节点上的每个摄影头都可以监视其父对象、自身及其直接子对象

计算监控树的所有节点所需的最小摄像头数量。

示例 1

输入: root = [0, 0, null, 0, 0]
输出: 1
解释: 如图所示,一台摄像头足以监控所有节点。

示例 2

输入: root = [0, 0, null, 0, null, 0, null, null, 0]
输出: 2
解释: 需要至少两个摄像头来监视树的所有节点。上图显示了摄像头放置的有效位置之一。

提示

  • 给定树的节点数的范围是[1, 1000]
  • 每个节点的值都是0

相关主题

  • 深度优先搜索
  • 动态规划
  • 二叉树

二、题解

#[derive(Debug, PartialEq, Eq)]
pub struct TreeNode {
    pub val: i32,
    pub left: Option<Rc<RefCell<TreeNode>>>,
    pub right: Option<Rc<RefCell<TreeNode>>>,
}

impl TreeNode {
    #[inline]
    pub fn new(val: i32) -> Self {
        TreeNode {
            val,
            left: None,
            right: None,
        }
    }
}

方法 1: 动态规划

pub fn min_camera_cover(root: Option<Rc<RefCell<TreeNode>>>) -> i32 {
    const DFS: fn(Option<Rc<RefCell<TreeNode>>>) -> (i32, i32, i32) = 
        |root| match root {
            None => (i32::MAX / 2, 0, 0),
            Some(curr) => {
                let (la, lb, lc) = DFS(curr.borrow_mut().left.take());
                let (ra, rb, rc) = DFS(curr.borrow_mut().right.take());

                // 状态a:`root`必须放置摄像头的情况下,覆盖整棵树需要的摄像头数目。
                // 状态b:覆盖整棵树需要的摄像头数目,无论`root`是否放置摄像头。
                // 状态c:覆盖两棵子树需要的摄像头数目,无论节点`root`本身是否被监控到。
                let a = lc + rc + 1;
                let b = min(a, min(la + rb, ra + lb));
                let c = min(a, lb + rb);

                (a, b, c)
            }
        };

    DFS(root).1
}

方法 2: 贪心

pub fn min_camera_cover(root: Option<Rc<RefCell<TreeNode>>>) -> i32 {
    const DFS: fn(Option<Rc<RefCell<TreeNode>>>, &mut i32) -> i32 = 
        |root, res| match root {
            None => 2,
            Some(curr) => {
                let left = DFS(curr.borrow_mut().left.take(), res);
                let right = DFS(curr.borrow_mut().right.take(), res);

                if left == 2 && right == 2 {
                    return 0;
                }

                if left == 0 || right == 0 {
                    *res += 1;
                    return 1;
                }

                if left == 1 || right == 1 {
                    return 2;
                }

                -1
            }
        };

    let mut res = 0;
    // 0:该节点无覆盖
    // 1:本节点有摄像头
    // 2:本节点有覆盖
    if DFS(root, &mut res) == 0 {
        res += 1;
    }

    res
}