Фотокамеры в двоичном дереве

Дано двоичное дерево, нам нужно установить в его узлах фотокамеры.

Камера в каждом узле мониторит сам узел, его родителя и его непосредственных детей.

Вычислить минимальное колчиество камер, которыми можно промониторить всё дерево.

Пример 1:

Дано: [0,0,null,0,0]
Результат: 1
Пояснение: Одной камеры достаточно, чтобы промониторить все узлы дерева, если установить её так, как показано на рисунке. 

Пример 2:

Дано: [0,0,null,0,null,0,null,null,0]
Результат: 2
Пояснение: По крайней мере 2 камеры нужны, чтобы мониторить всё дерево. На рисунке показана однеа из конфигураций расположения камер.


Примечания:

  1. Число узлов в дереве варбируется в интервале [1, 1000].
  2. Все узлы дерева имеют значение 0.

Идея решения 

Рассмотрим "внутренний" (не корневой и не листовой) узел в дереве. Он может мониториться камерой в родителе, в себе, в своих 2 детях. Итого: 4 узла задействованы.

Рассмотрим корневой узел дерева.. Он монтирится двумя детьми и собой. Итого: 3 узла задействованы.

Расммотрим листовой узел дерева. Он мониторится собой или своим родителем. Итого: 2 узла задействовано.
  1. Если мы расположим камеру в листе, то задействуем 2 узла (лист и его родитель).
  2. Если мы расположим камеру не в листе, а в его родителе, то она мониторит сам узел, его родителя и двух детей (могут быть листья).


Мы види м, что второй план действий лучше, чем первый. И таким образом, нам нужно устанавливать камеру в родителях листьев.

Жадное решение:

  • Установить камеры в листьях родителей и исключить из рассмотрения все промониторенные узлы (листья, их родители и родители родителей).
  • Повторить предыдущий шаг, пока все узлы не будут промониторены.

Алгоритмически: применим DFS. 

Типы узлов:

  • 0 (NOT_MONITORED), если узел - это лист, поэтому может мониториться сверху вниз от родителя. Узел может быть и не листом, но снизу до него не "долетает" мониторинг, поэтому мы считаем его листом.
  • 1 (MINITORED_WITHCAM), узел с камерой внутри, мониторит детей (узлы типа 0) и родителя (узел типа 2)
  • 2 (MONITORED_NOCAM), если узел мониторится камерой снизу вверх, установленной в узле-ребенке.

Для каждого узла:

  • если узлу нужна камера (у него есть дети, которые не мониторятся), то увеличиваем счётчик необходимых камер и возвращаем 1.
  • если уже мониторится снизу вверх, то возвращаем 2.
  • в противном случае (узел будет мониторится снизу вверх) возвращаем 0.

Имплементация

    class Solution {
    private int NOT_MONITORED = 0;
    
private int MONITORED_WITHCAM = 1; private int MONITORED_NOCAM = 2; private int cameras = 0; public int minCameraCover(TreeNode root) { if (root == null) return 0; int top = dfs(root); return cameras + (top == NOT_MONITORED ? 1 : 0); } private int dfs(TreeNode root) { if (root == null) return MONITORED_NOCAM; int left = dfs(root.left); int right = dfs(root.right);
if (left == MONITORED_NOCAM && right == MONITORED_NOCAM) {
// и слева и вправа дети мониторятся снизу вверх, занчит до текущего
// узла мониторинг не "долетает", значит он никак не мониторится return NOT_MONITORED; } else if (left == NOT_MONITORED || right == NOT_MONITORED) {
// слева или справа есть дети, которые не мониторятся, значит
// устанавливаем камеру в сам узел, увеличиваем счётчик камер cameras++; return MONITORED_WITHCAM; } else {
// наконец, сам узел мониторится камерой в одном из детей
             return MONITORED_NOCAM; } } }


 

Комментарии

Популярные сообщения из этого блога

Разбиение числа на сумму с максимальным произведнием слагаемых

Число подмассивов, в которых сумма элементов равна k

Сложить два числа, которые представлены списком