Ho una lista di numeri costanti. Ho bisogno di trovare il numero più vicino a x nella lista dei numeri. Qualche idea su come implementare questo algoritmo?Trova il numero più vicino in una lista di numeri
risposta
Bene, non è possibile farlo più veloce di O(N)
perché è necessario controllare tutti i numeri per essere sicuri di avere quello più vicino. Detto questo, perché non utilizzare una semplice variazione per trovare il minimo, cercando quello con la differenza assoluta minima con x?
Se si può dire che l'elenco è ordinato dall'inizio (e consente l'accesso casuale, come un array), un approccio migliore consiste nell'utilizzare una ricerca binaria. Quando si termina la ricerca all'indice i (senza trovare x), basta scegliere il meglio da quell'elemento e dai suoi vicini.
Esso può essere fatto utilizzando SortedList:
Blog post on finding closest number
Se la complessità che stai cercando conta solo la ricerca della complessità è O (log (n)). La costruzione della lista costerà O (n * log (n))
Se si intende inserire l'elemento nell'elenco più volte di quanto si sta per interrogarlo per il numero più vicino, la scelta migliore è quello di utilizzare List e utilizzare l'algoritmo naive per interrogarlo per il numero più vicino. Ogni ricerca avrà un costo O (n) ma il tempo di inserimento sarà ridotto a O (n).
complessità generale: Se la raccolta ha n numeri e cercato q volte -
Elenco: O(n+q*n)
elenco ordinato: O(n*log(n)+q*log(n))
significato, da qualche q la allineati la lista fornirà una migliore complessità.
private int? FindClosest(IEnumerable<int> numbers, int x)
{
return
(from number in numbers
let difference = Math.Abs(number - x)
orderby difference, Math.Abs(number), number descending
select (int?) number)
.FirstOrDefault();
}
Null significa che non c'era il numero più vicino. Se ci sono due numeri con la stessa differenza, sceglierà quello più vicino a zero. Se due numeri hanno la stessa distanza da zero, verrà scelto il numero positivo.
Modifica in risposta al commento di Eric:
Ecco una versione che ha la stessa semantica, ma utilizza l'operatore Min
. Richiede un'implementazione di IComparable<>
in modo da poter utilizzare Min
mantenendo il numero associato a ciascuna distanza. Ho anche reso un metodo di estensione per facilità d'uso:
public static int? FindClosestTo(this IEnumerable<int> numbers, int targetNumber)
{
var minimumDistance = numbers
.Select(number => new NumberDistance(targetNumber, number))
.Min();
return minimumDistance == null ? (int?) null : minimumDistance.Number;
}
private class NumberDistance : IComparable<NumberDistance>
{
internal NumberDistance(int targetNumber, int number)
{
this.Number = number;
this.Distance = Math.Abs(targetNumber - number);
}
internal int Number { get; private set; }
internal int Distance { get; private set; }
public int CompareTo(NumberDistance other)
{
var comparison = this.Distance.CompareTo(other.Distance);
if(comparison == 0)
{
// When they have the same distance, pick the number closest to zero
comparison = Math.Abs(this.Number).CompareTo(Math.Abs(other.Number));
if(comparison == 0)
{
// When they are the same distance from zero, pick the positive number
comparison = this.Number.CompareTo(other.Number);
}
}
return comparison;
}
}
Un affascinante uso di LINQ. Tuttavia, noto che questo è O (n lg n) nel tempo e O (n) nello spazio extra. Puoi farlo in O (n) time e O (1) di spazio se usi l'operatore di sequenza Min piuttosto che l'ordinamento. –
Inoltre, non hai ancora completamente disambiguato la dichiarazione del problema. Cosa succede se ci sono due numeri con la stessa differenza e entrambi sono ugualmente vicini a zero? –
Buon punto. Ho ordinato per 'numero decrescente' per garantire che il numero positivo sia scelto (in assenza di un requisito comportamentale, questa è la decisione più ragionevole). Lavorerò sulla soluzione 'Min'. Grazie per il tuo feedback Eric! –
Suppongo che l'array non sia ordinato. In ordine può essere più veloce
Penso che il metodo più semplice e veloce sia l'utilizzo di algoritmi lineari per la ricerca di minimo o massimo, ma invece di confrontare i valori si confronta il valore assoluto della differenza tra questo e l'ago.
In C++ (non riesco a C#, ma sarà simile) può codificare simile a questa:
// array of numbers is haystack
// length is length of array
// needle is number which you are looking for (or compare with)
int closest = haystack[0];
for (int i = 0; i < length; ++i) {
if (abs(haystack[ i ] - needle) < abs(closest - needle)) closest = haystack[i];
}
return closest;
È "ago" qualche nomenclatura speciale di cui non sono a conoscenza? –
"ago nel pagliaio": D –
"ago" e "pagliaio" sono espressioni che vengono spesso utilizzate con algoritmi di ricerca – Gaim
In generale le persone su questo sito non fare il vostro lavoro per voi. Dal momento che non hai inserito il codice, non invierò nemmeno il codice. Tuttavia, ecco un possibile approccio.
Passare attraverso l'elenco, sottraendo il numero nell'elenco da x. Prendi il valore assoluto di questa differenza e confrontalo con il miglior risultato precedente che hai ottenuto e, se la differenza attuale è inferiore al miglior risultato precedente, salva il numero corrente dalla lista. Alla fine del ciclo avrai la tua risposta.
L'OP ha utilizzato il tag "compiti a casa". Non sta provando a tirarne uno veloce. –
essere pigro non ho controllare questo, ma non deve questo lavoro
private int FindClosest(IEnumerable<int> numbers, int x)
{
return
numbers.Aggregate((r,n) => Math.Abs(r-x) > Math.Abs(n-x) ? n
: Math.Abs(r-x) < Math.Abs(n-x) ? r
: r < x ? n : r);
}
Haskell:
import Data.List (minimumBy)
import Data.Ord (comparing)
findClosest :: (Num a, Ord a) => a -> [a] -> Maybe a
findClosest _ [] = Nothing
findClosest n xs = Just $ minimumBy (comparing $ abs . (+ n)) xs
Performance wise custom code will be more use full.
List<int> results;
int targetNumber = 0;
int nearestValue=0;
if (results.Any(ab => ab == targetNumber))
{
nearestValue= results.FirstOrDefault<int>(i => i == targetNumber);
}
else
{
int greaterThanTarget = 0;
int lessThanTarget = 0;
if (results.Any(ab => ab > targetNumber))
{
greaterThanTarget = results.Where<int>(i => i > targetNumber).Min();
}
if (results.Any(ab => ab < targetNumber))
{
lessThanTarget = results.Where<int>(i => i < targetNumber).Max();
}
if (lessThanTarget == 0)
{
nearestValue= greaterThanTarget;
}
else if (greaterThanTarget == 0)
{
nearestValue= lessThanTarget;
}
else if (targetNumber - lessThanTarget < greaterThanTarget - targetNumber)
{
nearestValue= lessThanTarget;
}
else
{
nearestValue= greaterThanTarget;
}
}
- 1. Trova il bel numero più vicino
- 2. Python - Trova il numero più grande in una lista di numeri
- 3. Javascript trova il numero più vicino nell'array senza passare sotto
- 4. dalla lista di numeri interi, ottenere il numero più vicino ad un dato valore
- 5. Trova il numero in un array più vicino a un determinato numero
- 6. Finding più vicino numero in una gamma
- 7. numero tondo al numero intero più vicino
- 8. PHP - Trova il RGB più vicino a RGB predefinito dalla lista
- 9. Come posso contare il numero medio più vicino a 100?
- 10. Arrotonda al numero intero più vicino
- 11. rotondo al numero più vicino
- 12. Arrotondare al più alto numero intero più vicino in VBA
- 13. Trova il punto più vicino di un vettore di punti
- 14. Trova il valore più vicino in un elenco ordererd
- 15. Trova il numero più piccolo e il secondo più piccolo in un array di 8 numeri con solo 9 confronti
- 16. regex: trova il numero di una cifra
- 17. numero di arrotondamento a intervalli più vicino
- 18. Rubino: cifra tonda fino al più vicino numero in base elenco arbitrario di numeri
- 19. Trova il più piccolo tra 3 numeri in C++
- 20. Trova il valore più grande più piccolo di x in una matrice ordinata
- 21. Trova più vicino match è la stringa di input in una lettera di stringhe
- 22. Trova il genitore e l'elemento più vicino utilizzando jQuery
- 23. Trova numero univoco tra 3n + 1 numeri
- 24. Trova il valore numerico più vicino nel database
- 25. Dividere una lista di numeri in una lista più piccola con "somma" approssimativamente uguale
- 26. Ricerca di k numeri più vicini ad un dato numero
- 27. Ottenere prossimo numero più piccolo più vicino a un decimale
- 28. Trova/estrai una sequenza di numeri interi in una lista in python
- 29. LINQ per ottenere il valore più vicino?
- 30. Trova il numero più piccolo in un elenco di pitone e stampare la posizione
Si può utilizzare un elenco ordinato? –
Non dimenticare di considerare i casi insoliti. (1) cosa succede se non c'è il numero più vicino? e (2) cosa succede se ci sono due numeri più vicini? –