Per trovare più grande elemento più piccolo di K in un BST

voti
17

Dato un albero binario di ricerca e un intero K, mi piacerebbe trovare l'elemento più grande meno di K.

Nella struttura di seguito,

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

      10

  5       12

2   8   11  14

Ho provato la logica di seguito. Ma esiste un modo migliore per fare questo?

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;
}
È pubblicato 13/06/2011 alle 19:22
fonte dall'utente
In altre lingue...                            


5 risposte

voti
1

Suggerisco che si cammina attraverso il codice nell'implementazione locale del set :: superiore limite per la guida. Questa non è la soluzione al vostro problema esatto, ma molto vicino.

In generale, nella vita reale, la maggior parte di questi problemi non hanno bisogno di essere risolti nel proprio codice. STL può fare molte attività comuni per voi. E 'utile sapere come risolverli, naturalmente, da cui il test.

Risposto il 13/06/2011 a 19:29
fonte dall'utente

voti
3

Credo in utilizzando funzionalità della libreria standard. Così, la mia soluzione utilizza 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;
}
Risposto il 13/06/2011 a 19:33
fonte dall'utente

voti
19

Questo è O (log n), che è il minimo. Tuttavia, è possibile migliorare l'efficienza (che sembra essere la cosa principale questi intervistatori preoccupano) ed eliminare la possibilità di overflow dello stack (Tada!), Eliminando la ricorsione in coda, trasformando questo in un ciclo. Inoltre, il codice non funziona se l'albero contiene numeri negativi ... se si intende non negativi interi, si dovrebbe dire così, ma se l'intervistatore ha appena detto "interi", allora avete bisogno di codice leggermente diverso e un diverso API. (Si potrebbe mantenere la stessa firma funzione, ma tornare K invece di -1 in caso di errore.)

BTW, poiché questa è una questione intervista, la sua attuazione chiamando una funzione di libreria avrebbe detto la maggior parte degli intervistatori che sei un malandrina o manca il punto o non so come risolverlo. Non si scherza con questo genere di cose, basta avere a lavorare su ciò che si sa l'intervistatore vuole.

Ecco un'implementazione:

// 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;
}
Risposto il 13/06/2011 a 20:25
fonte dall'utente

voti
5

Penso che l'idea è quella di registrare l'ultimo nodo dopo di che si passa al sottoalbero destro. Pertanto, il codice verrà (è stato aggiornato)

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)
}
Risposto il 14/06/2011 a 03:06
fonte dall'utente

voti
1

Che la prima risposta, ha detto, e qui è la logica dietro perché non può ottenere meglio di O (log n). Stai cercando il maggior numero inferiore a K. Questo è abbastanza vicino a chiamare BST-ricerca / ottenere.

Anche se il vostro algoritmo originale sembra abbastanza buono, credo che questo sarebbe più veloce:

    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

    }
Risposto il 27/07/2011 a 11:11
fonte dall'utente

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