Если это дерево хранится в массиве, его можно переставить так, чтобы оно было «непрерывным по уровню» (первый элемент - это корень, следующие два его потомка, следующие четыре их потомка и т. Д.), И проблема тривиальна.
Если он хранится другим способом, это становится проблематичным.Вы можете попробовать обход в ширину, но это может занять O (n) памяти.
Ну, я думаю, вы можете создать алгоритм времени O (n log n), сохранив текущий уровень и путь ктекущий элемент (представленный в виде двоичного числа) и сохраняющий только последний посещенный элемент, чтобы иметь возможность создавать пары.Только O (1 + log n) памяти.-> Это может быть алгоритм O (n) с обратным отслеживанием (см. Ниже).
Я знаю, что существует простой алгоритм, который посещает все узлы по порядку в O (n), поэтому может быть хитростьпосещать «сестринские» узлы по порядку за O (n) время.Время O (n log n) гарантировано, но вы можете просто остановиться на данном уровне.
Существует также тривиальный алгоритм O (n log n), вам просто нужно отфильтровать узлы для данногоуровень, увеличивая уровень для следующего цикла.
Редактировать:
Хорошо, я создал решение, которое работает в O (n) с памятью O (1) (две переменные размера машинного слова дляотслеживайте текущий и максимальный уровень / который технически равен O (log log n) памяти, но давайте замаскируем этот / и несколько узлов), но для этого необходимо, чтобы все узлы содержали указатель на своего родителя.С помощью этой специальной структуры можно выполнять обход по порядку без стека O (n log n), используя только два узла для перехода влево, вверх или вправо.Вы останавливаетесь на определенном максимальном уровне и никогда не опускаетесь ниже него.Вы отслеживаете фактический и максимальный уровень, а также последний узел, который вы встретили на максимальном уровне.Очевидно, что вы можете распечатать такие пары, если встретите следующую на максимальном уровне.Вы увеличиваете максимальный уровень каждый раз, когда понимаете, что на этом уровне больше нет.
Начиная с корневого узла в двоичном дереве узла n-1, это составляет 1 + 3 + 7 + 15 + ... + n - 1 операция.Это 2 + 4 + 8 + 16 + ... + n - log2n = 2n - log2n = O (n) операций.
Без специальных Node* parent
членов этот алгоритм возможен только с O (log n) память из-за стека, необходимого для обхода по порядку.