Para encontrar el elemento más grande menor que K en un BST

votos
17

Dado un árbol binario de búsqueda y un entero K, me gustaría encontrar el elemento más grande menor K.

En el árbol de abajo,

for K = 13, result = 12
for K = 10, result = 8
for K = 1 (or) 2, result = -1

      10

  5       12

2   8   11  14

Probé la lógica continuación. Pero ¿hay alguna forma mejor de hacer esto?

int findNum(node* node, int K)
{
        if(node == NULL)
        {
                return -1;
        }
        else if(K <= node->data)
        {
                return findNum(node->left,K);
        }
        else if(K > node->data)
        {
                int t = findNum(node->right,K);
                return t > node->data ? t : node->data;
        }

        return -1;
}
Publicado el 13/06/2011 a las 19:22
fuente por usuario
En otros idiomas...                            


5 respuestas

votos
1

Sugiero que usted camina a través del código en su implementación local de set :: UPPER_BOUND de orientación. Esta no es la solución a su problema exacto, pero muy cerca.

En general, en la vida real, la mayoría de estos problemas no tienen que ser resueltos en su propio código. STL puede hacer muchas tareas comunes para usted. Es útil saber cómo resolver ellos, por supuesto, de ahí la prueba.

Respondida el 13/06/2011 a las 19:29
fuente por usuario

votos
3

Creo en el uso de las instalaciones de la biblioteca estándar. Por lo tanto, mi solución utiliza std::set. :-)

int largest_num_smaller_than(std::set<int> const& set, int num)
{
    std::set<int>::const_iterator lb(set.lower_bound(num));
    return lb == set.begin() ? -1 : *--lb;
}
Respondida el 13/06/2011 a las 19:33
fuente por usuario

votos
19

Eso es O (log n), que es el mínimo. Sin embargo, se puede mejorar la eficiencia (que parece ser el objetivo principal que estas se preocupan por los entrevistadores) y eliminar la posibilidad de desbordamiento de pila (Tada!) Mediante la eliminación de la recursión de cola, convirtiendo esto en un bucle. Además, su código no funciona si el árbol contiene los números negativos ... si usted quiere decir no negativos enteros, debería decirlo, pero si el entrevistador acaba de decir "enteros", entonces tienes código ligeramente diferente y una API diferente. (Se puede mantener la misma función, pero la firma K volver en lugar de -1 en caso de fallo.)

Por cierto, ya que esta es una pregunta de la entrevista, su aplicación llamando a una función de la biblioteca le diría a la mayoría de los entrevistadores que usted es un listillo o no viene al caso o no saben cómo resolverlo. No perder el tiempo con ese tipo de cosas, acaba de obtener a trabajar en lo que sabe que el entrevistador quiere.

Aquí es una implementación:

// Return the greatest int < K in tree, or K if none.
int findNum (Node* tree, int K)
{
    int val = K;

    while( tree )
        if( tree->data >= K )
            tree = tree->left;
        else{
            val = tree->data; 
            tree = tree->right;
        }

    return val;
}
Respondida el 13/06/2011 a las 20:25
fuente por usuario

votos
5

Creo que la idea aquí es para grabar el último nodo después de la cual se realiza el subárbol derecho. Por lo tanto, será (se ha actualizado) el código

int findNum (Node *node, int K)
{
    Node* last_right_move = NULL;

    while (node)
    {
        if (K<=node->data)
            node = node->left;
        else
        {
            last_right_move = node;
            node = node->right;
        }
    }

    if (last_right_move)
        return last_right_move->data;
    else
        return NOT_FOUND;  // defined previously. (-1 may conflict with negative number)
}
Respondida el 14/06/2011 a las 03:06
fuente por usuario

votos
1

Lo que la primera respuesta dijo, y aquí es la lógica detrás de por qué no puede ser mejor que O (log n). Que busca el número más grande de menos de K. Esto es bastante cercano a llamar BST-búsqueda / GET.

A pesar de que el algoritmo original se ve bastante bien, creo que esto sería más rápido:

    int findNum (node root, int K) {
        if(root == null) return -1;

        if(K > root.val) { 
           if(root.right != null) return findNum(root.right, K);               
           else return root.val; 
        }

        return findNum(root.left, K); //look in left subtree

    }
Respondida el 27/07/2011 a las 11:11
fuente por usuario

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more