【力扣roadmap】968. 监控二叉树

21 阅读2分钟

题目描述

  • 竞赛积分2124
  • 题号968

image.png

思路

我们给节点划分成三种状态:

  • 该节点没有被覆盖(在本题上下文中,称为没有被监控)记为状态0
  • 该节点是支配节点(在本题上下文中,称为有摄像头) 记为状态1
  • 该节点被覆盖(在本题上下文中,称为被监控)记为状态2

基于“叶子节点的父节点安装摄像头要优于叶子节点本身安装摄像头”的出发点,我们采用自底向上,后序遍历的方法。根据左右儿子节点的状态,推理出本节点的状态。

  • 如果左右儿子节点但凡有一个为未覆盖,那么父节点必须安装摄像头。此时答案加一,并且返回父节点的状态:1

  • 如果左右节点任意一个为有监控,那么父节点必为被覆盖,直接返回父节点状态:2

  • 如果左右节点全为状态2,那么推断当前父节点为未覆盖。但是你不要心急给答案加1说父节点必须装个摄像头,它按道理来说应该是不装摄像头,留给父节点的父节点去装,会更省一点。所以返回父节点的状态:0。

  • 特殊情况,如果最终判断根节点的状态为0,此时无人尝试覆盖根节点,无奈,只能特判一下:如果根节点无人覆盖,那么根节点只能特殊装一个摄像头。

代码

# 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:
        
        ans = 0
        def dfs(node) :
            nonlocal ans 
            if not node :
                return 2 
            l_res = dfs(node.left)
            r_res = dfs(node.right)
            if l_res == 0 or r_res == 0 :  #  子节点有无覆盖状态 那么父节点必须有监控
                ans += 1 
                return 1
            if l_res == r_res == 2 : # 子节点全为覆盖状态 那么父节点为无覆盖状态
                return 0
            if l_res == 1 or r_res == 1 :  # 子节点有监控 父节点则为覆盖状态
                return 2 
            
        
        if dfs(root) == 0 :
            ans += 1 
        return ans