Вот только набросок идеи:
В BST левое поддерево узла T
содержит только элементы, меньшие, чем значение, сохраненное в T
. Если k
меньше, чем количество элементов в левом поддереве, k
самый маленький элемент должен принадлежать левому поддереву. В противном случае, если k
больше, то k
наименьший элемент находится в правом поддереве.
Мы можем увеличить BST, чтобы каждый узел в нем сохранял количество элементов в своем левом поддереве (предположим, что левое поддерево данного узла включает этот узел). С помощью этой части информации легко обойти дерево, многократно запрашивая количество элементов в левом поддереве, чтобы решить, следует ли выполнять рекурсию в левое или правое поддерево.
Теперь предположим, что мы находимся в узле T:
- Если k == num_elements (левое поддерево T) , то ответ, который мы ищем, это значение в узле
T
.
- Если k> num_elements (левое поддерево T) , то очевидно, что мы можем игнорировать левое поддерево, поскольку эти элементы также будут меньше, чем
k
th самый маленький. Итак, мы сводим проблему к поиску k - num_elements(left subtree of T)
наименьшего элемента в правом поддереве.
- Если k , то
k
th самый маленький находится где-то в левом поддереве, поэтому мы уменьшаем проблему, чтобы найти k
th самый маленький элемент в левое поддерево.
Анализ сложности:
Это занимает O(depth of node)
времени, что составляет O(log n)
в худшем случае для сбалансированного BST или O(log n)
в среднем для случайного BST.
BST требует O(n)
хранения, и требуется еще O(n)
для хранения информации о количестве элементов. Все операции BST занимают O(depth of node)
времени, и требуется O(depth of node)
дополнительного времени для поддержания информации о "количестве элементов" для вставки, удаления или поворота узлов. Следовательно, хранение информации о количестве элементов в левом поддереве сохраняет пространственно-временную сложность BST.