Trouver la plus grande valeur inférieure à x dans un tableau sortingé

Supposons que j’ai un tableau sortingé d’entiers int[] et que je souhaite rechercher la valeur la plus petite et la plus proche d’un nombre en entrée.

Par exemple, si le tableau contient (1), (23), (57), (59), (120) et que l’entrée est 109, la sortie doit être 59.

J’essaie simplement de voir des suggestions et de me comparer aux approches que j’ai déjà.

Utilisez Array.BinarySearch . Si l’entrée est dans la liste, elle retournera l’index, sinon le complément de l’index de la première valeur la plus grande. Il vous suffit d’inverser le résultat et d’en soustraire un pour obtenir l’indice de la plus petite valeur la plus proche.

 int[] arr = { 1, 23, 57, 59, 120 }; int index = Array.BinarySearch(arr, 109); if (index < 0) { index = ~index - 1; } if (index >= 0) { var result = arr[index]; } 

Notez que si vous avez une entrée plus petite que le plus petit élément, vous n’avez pas de réponse bien définie.

en utilisant Linq:

 int[] arr = new[] { 1, 23, 57, 59, 120 }; int target = 109; int max = arr.Where(n => n < target).Max(); 

Peut-être pas le plus rapide mais probablement le plus facile à mettre en œuvre. De même, ne dépend pas du tableau en cours de sorting, comme le fait la recherche binary.

Notez que l'appel à Max lève une exception si le filtre Where produit aucun élément. Vous pouvez donc vérifier si c'est une possibilité.

Je préférerais une solution linq ( mise à jour : append un peu plus de code pour éviter d’être similaire à la solution similaire de fear):

 int[] arr1 = { 1, 23, 57, 59, 120 }; int maxResult; ssortingng errorMsg; try { maxResult = arr1.Where(x => x <= 109).Max(); } catch(Exception e) { errorMsg = e.Message; // do some error stuff here :) return null; } // party on your maxResult... 
 int getIndex( long[] list, long value ) { int top = 0; int bot = list.length-1; int mid=0; while ( top <= bot ) { mid = (top+bot)/2; // NB integer arithmetic if ( value < list[mid] ) { if ( mid == 0 ) // value < than first item return -1; else bot = mid-1; } else // value >= list[mid] { if ( mid == list.length-1 ) // value is >= last item break; else if ( value >= list[mid+1] ) top = mid+1; else // list[mid] must be biggest <= value break; } } return mid; } 

juste pour extrapoler sur les autres solutions LINQ, cette méthode d’extension retournera -1 si aucun object ne correspond au filtre et attend que la liste contienne tous des entiers positifs

 public static int SearchForLimit(this IEnuemerable sequence, Predicate filter) { return (from i in sequence let n = filter(i) ? i : -1 select n).Max() } 

l’utilisation ressemblerait à ceci:

 int[] arr1 = { 1, 23, 57, 59, 120 }; int limitedBy109 = arr1.SearchForLimit(i => i < 109);