目录

刷题记录-贪心-23968.-监控二叉树

刷题记录 贪心-23:968. 监控二叉树

题目:

难度:困难

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

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

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

示例 1:

https://i-blog.csdnimg.cn/img_convert/b9b280a99d44efe30326fb945d893468.png

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

示例 2:

https://i-blog.csdnimg.cn/img_convert/fd888cd1e435d5ff9309379f65ec7e29.png

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

提示:

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

一、模式识别

1.二叉树

二叉树类的题目的第一问题就是确定遍历顺序:这是极其重要的一点

检视节点 》 能同时考虑到左右孩子 》 后序

2.贪心

(1)定义三个状态: 暗节点, 监视器(灯),亮节点(被照亮)

代码实现:用哈希表记录信号强度,参照MC的红石电路,设定信号强度为2,每次衰减1

不在哈希表内:暗节点

值为2:监视器(灯)

值为1:亮节点(被照亮)

(2)如何放监视器并维护哈希表

①判断是否放置监视器的条件:有暗孩子(有孩子,且至少有一个暗节点孩子)

②如果有孩子是监视器,则设定本节点为亮节点

(3)贪心算法可能无法照顾到根节点

容易忽略的是这个方法容易把根节点略过根节点,

这个需要在代码最后打个补丁

二、代码实现

统一迭代法骨架 + 贪心判断:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def minCameraCover(self, root: Optional[TreeNode]) -> int:
        if not root.left and not root.right: return 1
        ans = 0
        stk = [root]
        cache = {}
        while stk:
            node = stk.pop()
            if node:
                stk.append(node)
                stk.append(None)
                if node.right: stk.append(node.right)
                if node.left: stk.append(node.left)
            else:
                node = stk.pop()
                if (node.left and node.left not in cache) or (node.right and node.right not in cache):
                    cache[node] = 2
                    ans += 1
                elif (node.left and cache[node.left] == 2) or (node.right and cache[node.right] == 2):
                    cache[node] = 1
        if root not in cache: ans += 1
        return ans

指针迭代法骨架 + 贪心判断:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def minCameraCover(self, root: Optional[TreeNode]) -> int:
        if not root.left and not root.right: return 1
        stk, node, prev = [], root, None
        cache = {}
        ans = 0
        while stk or node:
            while node:
                stk.append(node)
                node = node.left
            node = stk.pop()
            if not node.right or node.right == prev:
                if (node.left and node.left not in cache) or (node.right and node.right not in cache):
                    cache[node] = 2
                    ans += 1
                elif (node.left and cache[node.left] == 2) or (node.right and cache[node.right] == 2):
                    cache[node] = 1
                prev = node
                node = None
            else:
                stk.append(node)
                node = node.right
        if root not in cache: ans += 1
        return ans

递归:略,本题需要最后对根节点打补丁,用递归需要辅助函数,写起来比较繁琐