Questo algoritmo è O (1) spazio (con qualche imbroglio), O (n) (media), richiede la matrice di origine per essere non-const e distrugge alla fine. Inoltre limita i possibili valori nella matrice (tre bit di ciascun valore devono essere riservati all'algoritmo).
La metà della risposta è già nella domanda. Usa hashmap. Se un numero viene colpito due volte, usa la differenza indice, aggiorna il risultato migliore fino a quel momento e rimuovi questo numero dall'hashmap per liberare spazio. Per renderlo O (1) spazio, riutilizzare semplicemente l'array sorgente. Converti l'array in hashmap sul posto.
Prima di trasformare un elemento di matrice nella cella di hashmap, ricordarne il valore e la posizione. Dopo questo potrebbe essere sovrascritto in modo sicuro. Quindi utilizzare questo valore per calcolare una nuova posizione nella hashmap e sovrascriverla. Gli elementi vengono rimescolati in questo modo finché non viene trovata una cella vuota. Per continuare, seleziona qualsiasi elemento, che non è già riordinato. Quando tutto è riordinato, ogni coppia int è sicuramente colpita due volte, qui abbiamo una hashmap vuota e un valore di risultato migliore aggiornato.
Un bit riservato viene utilizzato durante la conversione di elementi di matrice nelle celle di hashmap. All'inizio è cancellato. Quando un valore viene riordinato alla cella hashmap, questo bit viene impostato. Se questo bit non è impostato per l'elemento sovrascritto, questo elemento è appena preso per essere elaborato successivamente. Se questo bit è impostato per la sovrascrittura dell'elemento, qui c'è un conflitto, selezionare il primo elemento non utilizzato (con questo bit non impostato) e sovrascriverlo.
2 altri bit riservati vengono utilizzati per concatenare valori in conflitto. Codificano le posizioni in cui la catena viene avviata/terminata/continuata. (Potrebbe essere possibile ottimizzare questo algoritmo in modo che siano necessari solo 2 bit riservati ...)
Una cella di hashmap deve contenere questi 3 bit riservati, l'indice del valore originale e alcune informazioni per identificare univocamente questo elemento. Per rendere ciò possibile, una funzione di hash dovrebbe essere reversibile in modo tale che parte del valore possa essere ripristinata data la sua posizione nella tabella. Nel caso più semplice, la funzione di hash è solo ceil(log(n))
bit meno significativi. Valore nella tabella è costituito da 3 campi:
3
bit riservati
32 - 3 - (ceil(log(n)))
bit di ordine dal valore originario
ceil(log(n))
bit per la posizione dell'elemento nell'array originale
Complessità è O (n) solo in media; la complessità peggiore è O (n^2).
Un'altra variante di questo algoritmo consiste nel trasformare sequenzialmente l'array in hashmap: su ogni passaggio m
con 2^m
primi elementi della matrice convertiti in hashmap. Alcuni array di dimensioni costanti possono essere intercalati con l'hashmap per migliorare le prestazioni quando m
è basso. Quando m
è alto, dovrebbero esserci abbastanza coppie int, che sono già state elaborate e che non richiedono più spazio.
Penso che tu possa chiaramente renderlo più veloce ... solo un suggerimento - nel tuo esempio, dopo aver scoperto che per 'a [0]' la distanza è '5', non devi controllare altri valori del tutto, dato che la dimensione se array è '6'. – lapk
@AzzA Ciò accelera sicuramente, tuttavia, non influenza il tasso di crescita asintotica lineare. –
Questa è una domanda di intervista? –