2009-10-08 12 views
3

J'ai un tableau d'entiers et j'ai besoin de trouver la position dans le tableau du nombre maximum avec le minimum. Je l'ai fonctionné mais cela ne semble pas être un très bon moyen de le faire. Quelqu'un peut-il suggérer une meilleure façon de réaliser ce que j'ai?Calcul des valeurs maximales et minimales dans un tableau

Voici mon code:

int[] usageHours = { 3, 3, 5, 4, 0, 0, 2, 2, 4, 25, 158, 320, 212, 356, 401, 460, 480, 403, 298, 213, 102, 87, 34, 45 }; 
double myAverage = usageHours.Average(); 
int runningTotal = 0; 
int runningMaxPosition = 0; 

for (int i = 0; i < usageHours.Length; i++) 
{ 
    if (usageHours[i] > runningTotal) 
    { 
     runningMaxPosition = i; 
     runningTotal = usageHours[i]; 
    } 
} 

txtmax.Text = Convert.ToString(runningMaxPosition)+" With: "+Convert.ToString(runningTotal)+" Users"; 
txtAv.Text = Convert.ToString(myAverage); 
+0

Thnaks l'aide et l'adivce. Maintenant, je vais devoir apprendre et apprendre mon code. – Tumble

Répondre

0

érafler le code LINQ, il ne marchait pas la façon dont vous vouliez

vous pouvez rendre votre code un peu plus concis

for (int i = 0; i < usageHours.Length; i++) 
{ 
    if (usageHours[i] > usageHours[runningMaxPosition]) 
     runningMaxPosition = i; 
} 

tout ce qu'il fait différemment est leavs sur la variable runningTotal temporaire.

+0

Il a besoin d'index de max et min, pas seulement leurs valeurs –

+0

Cela ne retourne-t-il pas les valeurs min et max *, et non les indices de tableau? –

+0

Je pense que vous avez tous les deux raison, laissez-moi changer ma réponse. –

2

Le code semble correct pour trouver la valeur maximale. Si vous utilisez C# 3 ou plus tard, vous pouvez utiliser les méthodes d'extension LINQ (il y a Min, Max et Average, et List il y a aussi une méthode FindIndex, mais j'ai l'impression que vous apprenez la programmation, et puis c'est parfois une bonne idée de mettre en œuvre des choses qui peuvent être intégrées dans le cadre, juste pour la valeur d'apprentissage.

+0

+1 parce que vous mentionnez l'apprentissage de la programmation sur l'utilisation du cadre. Le problème à résoudre a une durée d'exécution de O (n). Tous les nœuds doivent être vérifiés dans le tableau. Il est bon de comprendre ce que font les méthodes Linq et quel code n'a pas besoin d'être écrit à cause d'elles. Je suppose que le cours veut que les étudiants comprennent comment trouver les points de données, ne comprennent pas quelles fonctions existent pour trouver les points de données. – NerdFury

0

Que diriez-vous ceci:

double average = usageHours.Average(); 
int maxPosition = Enumerable.Range(0, usageHours.Length).Max(i => usageHours[i]); 
int minPosition = Enumerable.Range(0, usageHours.Length).Min(i => usageHours[i]); 
+2

Vous devez apprendre à marcher avant de pouvoir courir. C'est trop avancé pour un débutant. –

+0

O (3n), boucle sur la matrice 3 fois. Je sais que j'ai une obsession malsaine pour la performance, mais n'est-ce pas tout? – Andrew

7

Ce code est la plupart du temps très bien. Je suggère de changer un peu les noms des variables, mais c'est tout. Vous pouvez travailler le minimum dans la même boucle. J'ai modifié très légèrement les conditions «si» pour garantir qu'elles choisissent toujours au moins un élément (même si toutes les valeurs sont, disons, int.MinValue). Il y a d'autres façons d'aborder cela, mais c'est un exemple. Si vous avez un tableau vide, vous allez vous retrouver avec max = min = 0, et les deux index = -1.

int currentMax = 0; 
int currentMaxIndex = -1; 
int currentMin = 0; 
int currentMinIndex = -1; 

for (int i = 0; i < usageHours.Length; i++) 
{ 
    if (currentMaxIndex == -1 || usageHours[i] > currentMax) 
    { 
     currentMaxIndex = i; 
     currentMax = usageHours[i]; 
    } 
    if (currentMinIndex == -1 || usageHours[i] < currentMin) 
    { 
     currentMinIndex = i; 
     currentMin = usageHours[i]; 
    } 
} 

Voici une solution de rechange à l'aide types de valeur nullables pour représenter « il n'y avait pas de valeurs » réponses:

int currentMax? = null; 
int currentMaxIndex? = null; 
int currentMin? = null; 
int currentMinIndex? = null; 

for (int i = 0; i < usageHours.Length; i++) 
{ 
    if (currentMax == null || usageHours[i] > currentMax.Value) 
    { 
     currentMax = i; 
     currentMax = usageHours[i]; 
    } 
    if (currentMin == null || usageHours[i] < currentMin.Value) 
    { 
     currentMinIndex = i; 
     currentMin = usageHours[i]; 
    } 
} 

Ne vous inquiétez pas si vous n'êtes pas venu pour tous les types de valeur nullables encore bien. ..

+0

+1, non seulement cela est très instructif et aide à comprendre l'algorithme mais c'est aussi la méthode la plus rapide: O (n) –

+0

C'est la méthode la plus rapide. Les approches Linq suggérées exécutent plusieurs boucles sur le même tableau, ce qui les rend moins efficaces, mais avec un ordinateur moderne et sur un si petit tableau, vous ne remarquerez aucune différence. – Andrew

+0

+1 intelligent pour utiliser minvalue et maxvalue au lieu de 0, tous les nombres dans le tableau étant négatifs – TStamper

0

Votre code n'est pas mauvais, mais cela ne fonctionnera pas si toutes les valeurs sont inférieures à zéro.

Essayez ceci:

int getArrayMaxPosition (double[] theArray) 
{  
    double maxVal = theArray[0]; 
    int ret = 0; 
    int currentIndex = 0; 

    foreach (double aValue in theArray) 
    { 
     if (aValue > maxVal) 
     { 
      ret = currentIndex; 
      maxVal = avalue; 
     } 
     currentIndex++; 
    } 

    return ret; 
} 
0

Comme mentionné sur le commentaire de la réponse de Jon, la solution de Jon est vraiment le meilleur, le plus direct, le plus rapide de le faire.

Si, cependant, vous ne voulez utiliser la solution d'Igor, voici le reste (pour obtenir les positions réelles ainsi que les valeurs):

int maxValue = Enumerable.Range(0, usageHours.Length).Max(i => usageHours[i]); 
int maxPosition = Array.FindIndex(usageHours, i => i == maxValue); 
int minValue = Enumerable.Range(0, usageHours.Length).Min(i => usageHours[i]); 
int minPosition = Array.FindIndex(usageHours, i => i == minValue); 
1

Je voulais juste fournir une solution one-liner pour la question (pour l'exhaustivité). Dans la question initiale de l'OP, il demande seulement l'indice du maximum et l'indice du minimum.

Restons-en à cette question. C'est la question la plus intéressante car pour trouver la valeur maximale, nous pouvons simplement utiliser la méthode Enumerable.Max LINQ. La même chose vaut pour Min et Moyenne.

Indiquons seulement l'index du max, l'index de min peut être récupéré avec un code similaire.

int indexOfMax = Enumerable.Range(0, usageHours.Length).Aggregate(
    (indexOfMax, i) => (usageHours[i] > usageHours[indexOfMax] ? i : indexOfMax) 
); 

délégué à l'intérieur des supports de agrégat est exécutée pour chaque index de tableau. Il obtient comme paramètres "index de valeur maximale jusqu'ici trouvé", et index actuel. Il renvoie "l'index de la valeur maximum jusqu'ici trouvé". Évidemment, dans chaque itération, l '«indice de valeur maximale trouvé jusqu'ici» ne changera en index courant que si l'élément correspondant du tableau est supérieur au maximum précédent.

Questions connexes