C # trouve la valeur et l'index de tableau les plus élevés
89
J'ai donc un tableau numérique non trié int[] anArray = { 1, 5, 2, 7 };et j'ai besoin d'obtenir à la fois la valeur et l'index de la plus grande valeur du tableau qui serait 7 et 3, comment puis-je faire cela?
Jusqu'à présent, j'ai essayé d'utiliser la méthode Max (), puis d'utiliser la méthode de recherche binaire pour obtenir l'index de cette valeur maximale, mais cela ne fonctionne pas à moins que le tableau ne soit trié, donc je ne peux pas l'utiliser, quand j'ai essayé qu'il m'a donné des nombres négatifs
Edmund Rojas
@EdmundRojas Vous n'avez pas besoin d'utiliser la recherche binaire. Une recherche linéaire simple fonctionne très bien pour les listes non triées.
millimoose
Réponses:
138
Ce n'est pas la manière la plus glamour mais ça marche.
(doit avoir using System.Linq;)
int maxValue = anArray.Max();int maxIndex = anArray.ToList().IndexOf(maxValue);
Vous économisez beaucoup de temps de codage, mais vous finirez par parcourir la collection deux fois.
Garo Yeriazarian
11
Vous n'avez même pas besoin de l' .ToList()implémentation explicite des tableaux,IList
millimoose
@GaroYeriazarian Si la complexité linéaire est trop importante pour votre cas d'utilisation, vous devez probablement réduire plus que simplement réduire le facteur constant d'un tiers. (Bien que ce ne soit évidemment pas une optimisation négligeable.)
millimoose
1
@ sa_ddam213 Les tableaux implémentent l' IListinterface, mais ils le font explicitement: msdn.microsoft.com/en-us/library/… . (Les tableaux implémentent également l' IList<T>interface générique correspondante .)
millimoose
1
@ sa_ddam213 Non, le contrat ToList()est de toujours copier. Ce serait une idée terrible d'avoir la méthode parfois copiée et parfois non - cela conduirait à des bogues d'alias assez fous. En fait, la mise en œuvre de ToList()est plus ou moinsreturn new List(source)
millimoose
42
int[] anArray ={1,5,2,7};// Finding maxint m = anArray.Max();// Positioning maxint p =Array.IndexOf(anArray, m);
Si l'index n'est pas trié, vous devez parcourir le tableau au moins une fois pour trouver la valeur la plus élevée. J'utiliserais une forboucle simple :
int? maxVal =null;//nullable so this works even if you have all super-low negativesint index =-1;for(int i =0; i < anArray.Length; i++){int thisNum = anArray[i];if(!maxVal.HasValue|| thisNum > maxVal.Value){
maxVal = thisNum;
index = i;}}
C'est plus détaillé que quelque chose utilisant LINQ ou d'autres solutions en une ligne, mais c'est probablement un peu plus rapide. Il n'y a vraiment aucun moyen de rendre cela plus rapide que O (N).
Vous pouvez enregistrer une itération en initialisant maxValà la valeur du tableau à l'index 0 (en supposant que le tableau a au moins la longueur 1), indexà 0 et en commençant la boucle for à i = 1.
Jon Schneider
13
Le LINQ one [1] -liner obligatoire:
var max = anArray.Select((value, index)=>new{value, index}).OrderByDescending(vi => vi.value).First();
(Le tri est probablement un impact sur les performances par rapport aux autres solutions.)
Juste pour ajouter cette solution, c'est au mieux la complexité O (nlogn). La recherche de max peut être obtenue en temps O (n) pour un tableau non trié.
dopplesoldner
13
Un one-liner succinct:
var max = anArray.Select((n, i)=>(Number: n,Index: i)).Max();
Cas de test:
var anArray =newint[]{1,5,2,7};var max = anArray.Select((n, i)=>(Number: n,Index: i)).Max();Console.WriteLine($"Maximum number = {max.Number}, on index {max.Index}.");// Maximum number = 7, on index 4.
Fonctionnalités:
Utilise Linq (pas aussi optimisé que vanilla, mais le compromis est moins de code).
N'a pas besoin de trier.
Complexité de calcul: O (n).
Complexité spatiale: O (n).
Remarques:
Assurez-vous que le nombre (et non l'index) est le premier élément du tuple, car le tri par tuple est effectué en comparant les éléments de tuple de gauche à droite.
Il convient de noter que pour que cela fonctionne, l'élément maximal doit être le premier
Caius Jard
Que voulez-vous dire @CaiusJard? Comme indiqué dans le scénario de test, l'élément maximal a été correctement trouvé et il était le dernier.
Lesair Valmont
Premier dans le tuple, par exemple, anArray.Select((n, i) => ( Index: i, Number: n)).Max()trouve l'index max plutôt que le nombre max en raison de la façon dont les tuples sont comparés (item1 est le plus significatif, etc.)
Caius Jard
Assez juste @CaiusJard, j'ai ajouté une remarque pour le souligner. Merci.
Lesair Valmont
3
Voici deux approches. Vous souhaiterez peut-être ajouter une gestion lorsque le tableau est vide.
publicstaticvoidFindMax(){// Advantages: // * Functional approach// * Compact code// Cons: // * We are indexing into the array twice at each step// * The Range and IEnumerable add a bit of overhead// * Many people will find this code harder to understandint[]array={1,5,2,7};int maxIndex =Enumerable.Range(0,array.Length).Aggregate((max, i)=>array[max]>array[i]? max : i);int maxInt =array[maxIndex];Console.WriteLine($"Maximum int {maxInt} is found at index {maxIndex}");}publicstaticvoidFindMax2(){// Advantages: // * Near-optimal performanceint[]array={1,5,2,7};int maxIndex =-1;int maxInt =Int32.MinValue;// Modern C# compilers optimize the case where we put array.Length in the conditionfor(int i =0; i <array.Length; i++){intvalue=array[i];if(value> maxInt){
maxInt =value;
maxIndex = i;}}Console.WriteLine($"Maximum int {maxInt} is found at index {maxIndex}");}
publicstaticclassArrayExtensions{publicstaticintMaxIndexOf<T>(this T[] input){var max = input.Max();int index =Array.IndexOf(input, max);return index;}}
Cela fonctionne pour tous les types de variables ...
vararray=newint[]{1,2,4,10,0,2};var index =array.MaxIndexOf();vararray=newdouble[]{1.0,2.0,4.0,10.0,0.0,2.0};var index =array.MaxIndexOf();
Votre réponse ne donne que la valeur la plus élevée, mais le demandeur a demandé à la fois la valeur la plus élevée et l'indice de la valeur la plus élevée.
Cardin
0
Voici une solution LINQ qui est O (n) avec des facteurs constants décents:
Juste une autre perspective utilisant DataTable. Déclarez un DataTableavec 2 colonnes appelées indexet val. Ajoutez une AutoIncrementoption et des valeurs AutoIncrementSeedet à la colonne. Ensuite, utilisez une boucle et insérez chaque élément de tableau dans le sous forme de ligne. Ensuite, en utilisant method, sélectionnez la ligne ayant la valeur maximale.AutoIncrementStep1indexforeachdatatableSelect
Code
int[] anArray ={1,5,2,7};DataTable dt =newDataTable();
dt.Columns.AddRange(newDataColumn[2]{newDataColumn("index"),newDataColumn("val")});
dt.Columns["index"].AutoIncrement=true;
dt.Columns["index"].AutoIncrementSeed=1;
dt.Columns["index"].AutoIncrementStep=1;foreach(int i in anArray)
dt.Rows.Add(null, i);DataRow[] dr = dt.Select("[val] = MAX([val])");Console.WriteLine("Max Value = {0}, Index = {1}", dr[0][1], dr[0][0]);
Recherche le plus grand et le plus petit nombre du tableau:
int[] arr =newint[]{35,28,20,89,63,45,12};int big =0;int little =0;for(int i =0; i < arr.Length; i++){Console.WriteLine(arr[i]);if(arr[i]> arr[0]){
big = arr[i];}else{
little = arr[i];}}Console.WriteLine("most big number inside of array is "+ big);Console.WriteLine("most little number inside of array is "+ little);
Ceci est une version C #. Il est basé sur l'idée de trier le tableau.
publicint solution(int[] A){// write your code in C# 6.0 with .NET 4.5 (Mono)Array.Sort(A);var max = A.Max();if(max <0)return1;elsefor(int i =1; i < max; i++){if(!A.Contains(i)){return i;}}return max +1;}
/// <summary>/// Returns max value/// </summary>/// <param name="arr">array to search in</param>/// <param name="index">index of the max value</param>/// <returns>max value</returns>publicstaticintMaxAt(int[] arr,outint index){
index =-1;int max =Int32.MinValue;for(int i =0; i < arr.Length; i++){if(arr[i]> max){
max = arr[i];
index = i;}}return max;}
Usage:
int m, at;
m =MaxAt(newint[]{1,2,7,3,4,5,6},out at);Console.WriteLine("Max: {0}, found at: {1}", m, at);
Cela peut être fait avec une forboucle sans corps, si nous nous dirigeons vers le golf;)
//a is the arrayint mi = a.Length-1;for(int i=-1;++i<a.Length-1; mi=a[mi]<a[i]?i:mi);
Le contrôle des ++i<a.Length-1omet de vérifier le dernier index. Cela ne nous dérange pas si nous le configurons comme si l'index max était le dernier index avec lequel commencer. Lorsque la boucle s'exécute pour les autres éléments, elle se terminera et l'une ou l'autre chose est vraie:
nous avons trouvé une nouvelle valeur max et donc un nouvel index max mi
le dernier index était la valeur maximale tout au long, donc nous n'avons pas trouvé de nouveau mi, et nous sommes restés avec l'initialemi
Le vrai travail est effectué par les modificateurs post-boucle:
est la valeur max ( a[mi]c'est-à-dire le tableau indexé par mi) que nous avons trouvée jusqu'à présent, inférieure à l'élément actuel?
oui, puis stocker un nouveau mien se souvenant i,
non puis stocker l'existant mi(no-op)
À la fin de l'opération, vous avez l'index auquel le max doit être trouvé. Logiquement, la valeur maximale esta[mi]
Je ne pouvais pas vraiment voir comment le "find max and index of max" avait vraiment besoin de suivre la valeur max, étant donné que si vous avez un tableau et que vous connaissez l'indice de la valeur max, la valeur réelle de la valeur max est un cas trivial d'utilisation de l'index pour indexer le tableau.
Réponses:
Ce n'est pas la manière la plus glamour mais ça marche.
(doit avoir
using System.Linq;
)la source
.ToList()
implémentation explicite des tableaux,IList
IList
interface, mais ils le font explicitement: msdn.microsoft.com/en-us/library/… . (Les tableaux implémentent également l'IList<T>
interface générique correspondante .)ToList()
est de toujours copier. Ce serait une idée terrible d'avoir la méthode parfois copiée et parfois non - cela conduirait à des bogues d'alias assez fous. En fait, la mise en œuvre deToList()
est plus ou moinsreturn new List(source)
la source
Si l'index n'est pas trié, vous devez parcourir le tableau au moins une fois pour trouver la valeur la plus élevée. J'utiliserais une
for
boucle simple :C'est plus détaillé que quelque chose utilisant LINQ ou d'autres solutions en une ligne, mais c'est probablement un peu plus rapide. Il n'y a vraiment aucun moyen de rendre cela plus rapide que O (N).
la source
maxVal
à la valeur du tableau à l'index 0 (en supposant que le tableau a au moins la longueur 1),index
à 0 et en commençant la boucle for ài = 1
.Le LINQ one [1] -liner obligatoire:
(Le tri est probablement un impact sur les performances par rapport aux autres solutions.)
[1]: Pour des valeurs données de "un".
la source
Un one-liner succinct:
Cas de test:
Fonctionnalités:
Remarques:
la source
anArray.Select((n, i) => ( Index: i, Number: n)).Max()
trouve l'index max plutôt que le nombre max en raison de la façon dont les tuples sont comparés (item1 est le plus significatif, etc.)Voici deux approches. Vous souhaiterez peut-être ajouter une gestion lorsque le tableau est vide.
la source
la source
la source
Sortie pour le code ci-dessous:
00: 00: 00.3279270 - max1 00: 00: 00.2615935 - max2 00: 00: 00.6010360 - max3 (arr.Max ())
Avec 100000000 ints en tableau, ce n'est pas une très grande différence mais quand même ...
la source
Cela fonctionne pour tous les types de variables ...
la source
la source
la source
Voici une solution LINQ qui est O (n) avec des facteurs constants décents:
Mais vous devriez vraiment écrire un
for
lop explicite si vous vous souciez des performances.la source
Juste une autre perspective utilisant
DataTable
. Déclarez unDataTable
avec 2 colonnes appeléesindex
etval
. Ajoutez uneAutoIncrement
option et des valeursAutoIncrementSeed
et à la colonne. Ensuite, utilisez une boucle et insérez chaque élément de tableau dans le sous forme de ligne. Ensuite, en utilisant method, sélectionnez la ligne ayant la valeur maximale.AutoIncrementStep
1
index
foreach
datatable
Select
Code
Production
Trouvez une démo ici
la source
Recherche le plus grand et le plus petit nombre du tableau:
la source
Si vous connaissez max index, l'accès à la valeur max est immédiat. Donc, tout ce dont vous avez besoin est un index max.
la source
Ceci est une version C #. Il est basé sur l'idée de trier le tableau.
la source
Pensez à suivre:
Usage:
la source
Cela peut être fait avec une
for
boucle sans corps, si nous nous dirigeons vers le golf;)Le contrôle des
++i<a.Length-1
omet de vérifier le dernier index. Cela ne nous dérange pas si nous le configurons comme si l'index max était le dernier index avec lequel commencer. Lorsque la boucle s'exécute pour les autres éléments, elle se terminera et l'une ou l'autre chose est vraie:mi
mi
, et nous sommes restés avec l'initialemi
Le vrai travail est effectué par les modificateurs post-boucle:
a[mi]
c'est-à-dire le tableau indexé parmi
) que nous avons trouvée jusqu'à présent, inférieure à l'élément actuel?mi
en se souvenanti
,mi
(no-op)À la fin de l'opération, vous avez l'index auquel le max doit être trouvé. Logiquement, la valeur maximale est
a[mi]
Je ne pouvais pas vraiment voir comment le "find max and index of max" avait vraiment besoin de suivre la valeur max, étant donné que si vous avez un tableau et que vous connaissez l'indice de la valeur max, la valeur réelle de la valeur max est un cas trivial d'utilisation de l'index pour indexer le tableau.
la source