Хотя вы можете найти максимальную глубину в O (n), основываясь на вашем массиве родителей, как описано Matej, возможно, стоит преобразовать этот массив в древовидную структуру, более удобную для навигации в направлении от родителя к ребенкуузел.Вы уже делаете это с вашим классом Node
, но ваш метод fillChildren
имеет сложность O (n²), так как вам приходится сканировать весь массив снова и снова, чтобы найти дочерние элементы текущего узла.
Вместо этогоВы можете создать Map<Integer, Set<Integer>>
, сопоставляя узлы их дочерним узлам.Таким образом, вы можете создать все дерево в одном цикле над массивом в O (n).
static Map<Integer, Set<Integer>> makeTree(int[] parents) {
Map<Integer, Set<Integer>> tree = new HashMap<>();
for (int i = 0; i < parents.length; i++) {
tree.computeIfAbsent(parents[i], x -> new HashSet<>()).add(i);
}
return tree;
}
Затем вы можете легко написать рекурсивную функцию для получения максимальной глубины дерева:
static int depth(Map<Integer, Set<Integer>> tree, int node) {
return tree.containsKey(node)
? 1 + tree.get(node).stream().mapToInt(n -> depth(tree, n)).max().getAsInt()
: 0;
}
Сложность для обоих шагов равна O (n), если массив представляет собой дерево, поскольку каждый узел посещается ровно один раз.Если массив может также показать ориентированный граф, вы должны отслеживать уже посещенные ранее узлы.Для вашего примера используйте его так:
int[] array = {4, -1, 4, 1, 1};
Map<Integer, Set<Integer>> tree = makeTree(array);
System.out.println(depth(tree, -1)); // 3
Как и в любом рекурсивном алгоритме, он может достичь максимальной глубины рекурсии, если дерево очень и очень глубокое.Он может быть переписан итеративным способом с использованием Stack
, но не будет таким кратким.
Stack<Integer> stack = new Stack<>();
stack.add(-1);
int[] depth = new int[array.length];
while (! stack.isEmpty()) {
int node = stack.pop();
for (Integer child : tree.getOrDefault(node, Collections.emptySet())) {
depth[child] = node == -1 ? 1 : depth[node] + 1;
stack.add(child);
}
}
System.out.println(IntStream.of(depth).max().getAsInt());