【路飞】监控二叉树

341 阅读2分钟

记录 1 道算法题

监控二叉树

leetcode-cn.com/problems/bi…


这道题很难,难在怎么确定遍历的方法和记录哪里有相机。

一开始看到了一种做法,是从上往下的,传递父节点是否被监控,本节点有没有相机。然后我复刻了一下函数大概长这样, f(root, hasCamera, parentStatus)。然后到了第160个测试用例的时候,超时了。里面是一步步往前摸索, Math.min(...)。发现从上面一直往下通知状态的方法没法进一步改造之后,又去看题解。贪心思想果然写起来就比之前的简单。

贪心思想是从下面开始往上传递状态,所以用后序遍历。然后进行可能性的总结。

  • 节点没有被监视 0
  • 节点有摄像机 2
  • 节点被监视 1
        a
     b     c

当 b 节点为 0 ,没有被监视的时候,a 应该是 2 装相机。因为是从下往上,如果这一层不处理, b 节点就消失了。

然后 b 和 c 节点都被覆盖的时候,a 节点应该是 0。为什么不能是 1 呢,是因为在

还有一种情况就是当遍历到叶子节点的时候,叶子节点的状态是什么,但是基于贪心思想,应该尽量在更上面的节点装相机。所以叶子节点应该是被监视状态。

最后根节点要判断,如果左右子节点都是被监视状态,那还要额外加 1

以上就是递归时的操作,每一次都可以看作是这种树,只是节点有不同的状态。

    function minCameraCover(root) {
        let count = 0
        function f(root) {
          if (!root) return 1
          
          // 后序遍历
          const left = f(root.left)
          const right = f(root.right)
          if (left === 0 || right === 0) {
            count++
            return 2
          }

          if (left === 1 && right === 1) return 0

          if (left === 2 || right === 2) return 1
        }
        
        // 当左右子节点都已经被监视的时候,只剩一个孤零零的根节点
        return f(root) === 0 ? count + 1 : count
   }