Фотокамеры в двоичном дереве
Дано двоичное дерево, нам нужно установить в его узлах фотокамеры.
Камера в каждом узле мониторит сам узел, его родителя и его непосредственных детей.
Вычислить минимальное колчиество камер, которыми можно промониторить всё дерево.
Пример 1:

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

Дано: [0,0,null,0,null,0,null,null,0] Результат: 2 Пояснение: По крайней мере 2 камеры нужны, чтобы мониторить всё дерево. На рисунке показана однеа из конфигураций расположения камер.
Примечания:
- Число узлов в дереве варбируется в интервале
[1, 1000]. - Все узлы дерева имеют значение 0.
Идея решения
Рассмотрим "внутренний" (не корневой и не листовой) узел в дереве. Он может мониториться камерой в родителе, в себе, в своих 2 детях. Итого: 4 узла задействованы.Рассмотрим корневой узел дерева.. Он монтирится двумя детьми и собой. Итого: 3 узла задействованы.
Расммотрим листовой узел дерева. Он мониторится собой или своим родителем. Итого: 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;
}
}
}
Комментарии
Отправить комментарий