Одним из способов решения этой проблемы является использование факта, что обход дерева по порядку будет производить все элементы в отсортированном порядке.Если вы можете обнаружить отклонения от отсортированного порядка во время этой прогулки, вы можете попытаться найти два элемента, которые находятся в неправильном месте.
Давайте сначала посмотрим, как это сделать для простого отсортированного массива, а затем будем использоватьнаш алгоритм построения чего-то, что работает на деревьях.Интуитивно понятно, что если мы начнем с отсортированного массива, а затем поменяем местами два (не равных!) Элемента, то получится, что некоторое количество элементов в массиве будет неуместным.Например, учитывая массив
1 2 3 4 5
Если мы поменяем местами 2 и 4, мы получим этот массив:
1 4 3 2 5
Как бы мы обнаружили, что 2 и 4 поменялись местами здесь?Ну, так как 4 является наибольшим из двух элементов и был поменялся местами, он должен быть больше, чем оба элемента вокруг него.Точно так же, поскольку 2 поменялся местами, он должен быть меньше, чем оба элемента вокруг него.Отсюда можно сделать вывод, что 2 и 4 поменялись местами.
Однако это не всегда работает правильно.Например, предположим, что мы меняем 1 и 4:
4 2 3 1 5
Здесь 2 и 1 меньше, чем их соседние элементы, а 4 и 3 больше, чем их.Из этого мы можем сказать, что два из этих четырех так или иначе были обменены, но не ясно, какие из них мы должны поменяться местами.Однако, если мы возьмем самое большое и самое маленькое из этих значений (1 и 4 соответственно), мы получим пару, которая была поменяна местами.
В общем, чтобы найти элементы, которые поменялись местами в последовательности, вы хотите найти
- Наибольший локальный максимум в массиве.
- Наименьший локальный минимум в массиве.
Эти два элемента отсутствуютместа и должны быть поменяны местами.
Теперь давайте подумаем, как применить это к деревьям.Так как обход дерева по порядку будет производить сортированную последовательность с двумя элементами не по порядку, одним из вариантов будет обход дерева, записывая последовательность по порядку найденных элементов, а затем используя вышеуказанный алгоритм.Например, рассмотрим исходный BST:
20
/ \
15 30
/ \ / \
10 17 25 33
/ | / \ / \ | \
9 16 12 18 22 26 31 34
Если мы линеаризуем это в массив, мы получим
9 10 16 15 12 17 18 20 22 25 26 30 31 33 34
Обратите внимание, что 16 больше, чем окружающие его элементы, и что 12 меньшечем его.Это немедленно говорит нам о том, что 12 и 16 поменялись местами.
Следовательно, простым алгоритмом для решения этой проблемы было бы выполнить обход дерева по порядку, чтобы линеаризовать его в последовательность, такую как vector
или deque
, затем сканировать эту последовательность, чтобы найти наибольший локальный максимум и наименьший локальный минимум.Это будет выполняться за время O (n), используя пространство O (n).Более хитрым, но более экономичным по площади алгоритмом было бы отслеживать только три узла одновременно - текущий узел, его предшественника и его преемника - что уменьшает использование памяти до O (1).
Надеюсьэто помогает!