Как найти ближайший элемент к заданному значению ключа в двоичном дереве поиска?

Учитывая bst с целыми значениями в качестве ключей, как найти ближайший node к этому ключу в bst? BST представлен с использованием объекта узлов (Java). Ближайшим будет, например, 4,5,9, и если ключ равен 6, он вернется 5..

Ответы

Ответ 1

Поверните дерево так, как вы бы нашли этот элемент. Пока вы делаете эту запись, значение, которое ближе всего к вашему ключу. Теперь, когда вы не нашли node для самого ключа, возвращайте записанное значение.

Итак, если вы искали ключ 3 в следующем дереве, вы попали бы в node 6, не найдя соответствия, но ваше записанное значение было бы 2, поскольку это был самый близкий ключ все узлы, которые вы прошли (2, 7, 6).

                 2
              1      7
                   6   8

Ответ 2

Траверс принимает время O (n). Можем ли мы продолжить его в верхнем дне? как этот рекурсивный код:

Tnode * closestBST(Tnode * root, int val){
    if(root->val == val)
        return root;
    if(val < root->val){
        if(!root->left)
            return root;
        Tnode * p = closestBST(root->left, val);
        return abs(p->val-val) > abs(root->val-val) ? root : p;
    }else{
        if(!root->right)
            return root;
        Tnode * p = closestBST(root->right, val);
        return abs(p->val-val) > abs(root->val-val) ? root : p;
    }   
    return null;
}

Ответ 3

Здесь рекурсивное решение в Python:

def searchForClosestNodeHelper(root, val, closestNode):
    if root is None:
        return closestNode

    if root.val == val:
        return root

    if closestNode is None or abs(root.val - val) < abs(closestNode.val - val):
        closestNode = root

    if val < root.val:
        return searchForClosestNodeHelper(root.left, val, closestNode)
    else:
        return searchForClosestNodeHelper(root.right, val, closestNode)

def searchForClosestNode(root, val):
    return searchForClosestNodeHelper(root, val, None)

Ответ 4

Он может быть решен в O (log * n *) времени.

  • Если значение в node такое же, как заданное значение, это ближайший node;
  • Если значение в node больше заданного значения, перейдите к левому дочернему элементу,
  • Если значение в node меньше заданного значения, перейдите в правый дочерний элемент.

Алгоритм может быть реализован со следующим кодом С++:

BinaryTreeNode* getClosestNode(BinaryTreeNode* pRoot, int value)
{
    BinaryTreeNode* pClosest = NULL;
    int minDistance = 0x7FFFFFFF;
    BinaryTreeNode* pNode = pRoot;
    while(pNode != NULL){
        int distance = abs(pNode->m_nValue - value);
        if(distance < minDistance){
            minDistance = distance;
            pClosest = pNode;
        }

        if(distance == 0)
            break;

        if(pNode->m_nValue > value)
            pNode = pNode->m_pLeft;
        else if(pNode->m_nValue < value)
            pNode = pNode->m_pRight;
    }

    return pClosest;
}

Вы можете посетить мой блог для более подробной информации.

Ответ 5

Проблема с подходом "левый правый обход и поиск ближайшего" заключается в том, что он зависит от последовательности, в которой элементы были введены для создания BST. Если мы ищем 11 для последовательности BST 22, 15, 16, 6, 14, 3, 1, 90, вышеуказанный метод вернет 15, а правильный ответ - 14. Единственный метод должен использовать рекурсию для перемещения всех узлов, возвращая ближайшую из них в результате рекурсивной функции. Это даст нам самое близкое значение

Ответ 6

Это можно сделать с помощью Queue и ArrayList. Очередь будет использоваться для выполнения первого поиска по дереву. ArrayList будет использоваться для хранения элемента дерева в первом порядке. Вот код для реализации того же

Queue queue = new LinkedList();
ArrayList list = new ArrayList();
int i =0;
public Node findNextRightNode(Node root,int key)
{
    System.out.print("The breadth first search on Tree : \t");      
    if(root == null)
        return null;

    queue.clear();
    queue.add(root);

    while(!queue.isEmpty() )
    {
        Node node = (Node)queue.remove();
        System.out.print(node.data + " ");
        list.add(node);
        if(node.left != null) queue.add(node.left);
        if(node.right !=null) queue.add(node.right);            
    }

    Iterator iter = list.iterator();
    while(iter.hasNext())
        {
            if(((Node)iter.next()).data == key)
            {
                return ((Node)iter.next());
            }               
        }

    return null;
}

Ответ 7

void closestNode(Node root, int k , Node result) {
    if(root == null) 
    {
       return;      //currently result is null , so it  will be the result
    }
    if(result == null || Math.abs(root.data - k) < Math.abs(result.data - k) )
    {
      result == root;
    }
    if(k < root.data)
    {
    closestNode(root.left, k, result)
    } 
    else 
    {
        closestNode(root.right, k, result);
    }

}

Ответ 8

Ниже один работает с разными образцами, которые у меня есть.

public Node findNearest(Node root, int k) {
    if (root == null) {
        return null;
    }
    int minDiff = 0;
    Node minAt = root;
    minDiff = Math.abs(k - root.data);

    while (root != null) {
        if (k == root.data) {
            return root;
        }
        if (k < root.data) {
            minAt = updateMin(root, k, minDiff, minAt);
            root = root.left;
        } else if (k > root.data) {
            minAt = updateMin(root, k, minDiff, minAt);
            root = root.right;
        }

    }
    return minAt;
}

private Node updateMin(Node root, int k, int minDiff, Node minAt) {
    int curDif;
    curDif = Math.abs(k - root.data);
    if (curDif < minDiff) {
        minAt = root;
    }
    return minAt;
}

Ответ 9

Самое простое решение - вернуть свое дерево с тех пор, как

  • вы найдете элемент
  • вы достигаете листа. В этом случае вы должны сделать пару сравнений, чтобы определить, является ли ближайшее значение листом или родителем листа.

До вас реализация.