【Leetcode】968. Binary Tree Cameras

题目地址:

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]))};
  }
};

时空复杂度一样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值